C ++将派生类作为基类模板参数

时间:2015-08-25 14:43:27

标签: c++ templates

我无法传递从DerivedObject派生的类DerivedClass(类BaseClass的一部分派生自模板类BaseObject)(模板类的一部分{ {1}})作为模板类BaseClass的模板参数。

这样,Base和Derived类都可以访问对象池,该对象池可以包含派生对象。这听起来有点令人困惑,所以这是一个例子:

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

有办法做到这一点吗?如果没有,是否有更好的解决方案可以提供相同/相似的功能?

4 个答案:

答案 0 :(得分:5)

此时

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
    }
};

答案 1 :(得分:1)

从您的示例代码中,我得到的印象是您希望为不同的基类提供不同的实现。使用模板有什么特殊原因吗?如果没有,您可以使用经典多态:

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将提供虚拟或纯虚函数 - 如您所愿。

但是,有一件事你会失去这种方式:保证在向量中始终存在一个特定BaseObject子类型的对象。如果这对您很重要,则可以保护池,并且只允许通过DerivedClass添加新的BaseObject。如果这不适用,我可能会想到BaseClass中的另一个解决方案。

答案 2 :(得分:1)

这是做出类似于所要求的事情的一种方式:

#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                                                                                                                                                                                                             
    }
};

答案 3 :(得分:0)

如果您不介意将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