传递一个派生类作为基类模板参数
C++ Passing a derived class as a base class template parameter
我在传递从BaseObject
(模板类BaseClass
的一部分)派生的类DerivedObject
(从模板类BaseClass
派生的类DerivedClass
的一部分)作为模板参数到模板类BaseClass
时遇到了麻烦。
这样,基类和派生类都可以访问对象池,对象池可以包含派生对象。这听起来有点令人困惑,下面是示例:
template <class TDerivedClass, class TDerivedObject>
class BaseClass
{
protected:
class BaseObject
{
// Class implementation
}
void foo()
{
static_cast<TDerivedClass*>(this)->foo();
}
std::vector<TDerivedObject*> m_objectPool;
};
以上是基类的实现。
error C2065: 'DerivedObject' undeclared identifier
上面的错误是由下面类定义的第一行引起的:
class DerivedClass : public BaseClass<DerivedClass, DerivedClass::DerivedObject>
{
protected:
class DerivedObject : public BaseObject
{
// Class implementation
}
void foo()
{
// Method implementation
}
};
有办法做到这一点吗?如果没有,是否有更好的解决方案,可以给我相同/类似的功能?
此时
class DerivedClass : public BaseClass<DerivedClass, DerivedClass::DerivedObject>
编译器没有看到DerivedClass::DerivedObject
,所以你得到一个未声明的标识符错误。由于没有看到它们的类型,因此不能将其用作模板参数。你没有得到一个DerivedClass
,因为你已经将DerivedClass
声明为class
。
你可以改变你的基类,让它存储一个std::vector<BaseObject*>
如果你这样做,你可以改变你的代码:
template <class TDerivedClass>
class BaseClass
{
protected:
class BaseObject
{
// Class implementation
};
void foo()
{
static_cast<TDerivedClass*>(this)->foo();
}
std::vector<BaseObject*> m_objectPool;
};
class DerivedClass : public BaseClass<DerivedClass>
{
protected:
class DerivedObject : public BaseObject
{
// Class implementation
};
void foo()
{
// Method implementation
}
};
这里有一种类似于请求的方法:
#include <vector>
using std::vector;
template <class TDerivedClass, class TDerivedObject>
class BaseClass
{
public:
class BaseObject
{
// Class implementation
};
protected:
// void foo()
// {
// static_cast<TDerivedClass*>(this)->foo();
// }
// std::vector<TDerivedObject*> m_objectPool;
};
class DerivedClass;
class DerivedObject : public BaseClass<DerivedClass, DerivedObject>::BaseObject
{
// Class implementation
};
class DerivedClass : public BaseClass<DerivedClass, DerivedObject>
{
public:
void foo()
{
// Method implementation
}
};
从您的示例代码中,我得到的印象是您希望为不同的基类提供不同的实现。使用模板有什么特殊的原因吗?如果没有,可以使用经典多态性:
class BaseClass
{
class BaseObject {};
virtual ~BaseClass() {} // <- do not forget to provide virtual dtor!
virtual void foo() = 0;
std::vector<BaseObject*> m_objectPool;
};
class DerivedClass : public BaseClass
{
class DerivedObject : public BaseObject {/*...*/};
virtual void foo(){/*...*/}
};
同样,BaseObject可以根据需要提供虚函数或纯虚函数。
但是,这样做会丢失一件事:在vector中始终存在一个特定BaseObject子类型的对象的保证。如果这对您很重要,您可以保护池,只允许通过DerivedClass添加新的BaseObjects。如果这是不适用的,我可能会想到从BaseClass内的另一个解决方案。如果您不介意将DerivedObject结构与DerivedClass分开,您可以这样做:
template <class T>
struct ObjectTypeTrait
{
static_assert(sizeof(T) == 0, "undefined trait");
};
template <class TDerivedClass>
class BaseClass
{
protected:
class BaseObject
{
// Class implementation
};
void foo()
{
static_cast<TDerivedClass*>(this)->foo();
}
std::vector<typename ObjectTypeTrait<TDerivedClass>::obj*> m_objectPool;
};
class DerivedClass;
class DerivedObject
{
// Class implementation
};
template<>
struct ObjectTypeTrait<DerivedClass>
{
using obj = DerivedObject;
};
class DerivedClass : public BaseClass<DerivedClass>
{
protected:
void foo()
{
// Method implementation
}
};
我不认为这是一个非常聪明的解决方案,但你可以得到的想法-使用类型特征或typedef
相关文章:
- 如何使基类的运算符对基类的可变参数数可见(请参阅下面的代码)?
- 命名参数习惯用法和(抽象)基类
- C++重载函数,一个采用基类的参数,另一个采用派生类的参数
- 如何允许模板参数中的类类型,仅当它有两个基类时
- 为什么我需要在成员发起器列表中重复基类的模板参数?
- 如何在不使用指针的情况下将派生类的对象作为参数传递给基类中的函数?
- C++17 使用驱动类常量作为基类构造函数的参数来初始化基类构造函数
- 根据参数数调用 mixin 基类的构造函数
- 派生类(构造函数具有参数)和基类(构造函数缺少参数)之间没有可行的转换
- 如何将子类作为函数的参数传递给期望基类,然后将该对象传递到指向这些抽象类对象的指针向量中?
- 在C++单元测试上下文中,抽象基类是否应将其他抽象基类作为函数参数
- C++ 如何使派生类自动获取基类参数
- 将派生类作为参数传递给方法,该方法是具有智能指针的基类
- 将函数上调整到基类参数的另一个
- 将派生类对象传递给具有 C++ 中基类参数的函数时,为什么要传递引用而不是值?
- 如何使用派生类中的虚拟函数,该函数在另一个具有基类参数的类中声明
- 将基类 2 参数构造函数调用到子类 1 参数构造函数中
- 指向友元函数中基类参数类型的指针
- 按值传递共享指针并接受作为基类参数是如何工作的
- 为带有基类参数的派生类参数调用函数重载