2010-05-20 165 views
3

我遇到了来自同一模板类的不同实例的多重继承问题。具体来说,我试图做到这一点:模板类的多继承

template <class T> 
class Base 
{ 

public: 

    Base() : obj(NULL) 
    { 
    } 

    virtual ~Base() 
    { 
     if(obj != NULL) delete obj; 
    } 

    template <class T> 
    T* createBase() 
    { 
     obj = new T(); 

     return obj; 
    } 

protected: 

    T* obj; 

}; 

class Something 
{ 
    // ... 
}; 

class SomethingElse 
{ 
    // ... 
}; 

class Derived : public Base<Something>, public Base<SomethingElse> 
{ 

}; 

int main() 
{ 
    Derived* d = new Derived(); 
    Something* smth1 = d->createBase<Something>(); 
    SomethingElse* smth2 = d->createBase<SomethingElse>(); 

    delete d; 

    return 0; 
} 

当我尝试编译上面的代码,我得到以下错误:

1>[...](41) : error C2440: '=' : cannot convert from 'SomethingElse *' to 'Something *' 
1>  Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast 
1>  [...](71) : see reference to function template instantiation 'T *Base<Something>::createBase<SomethingElse>(void)' being compiled 
1>  with 
1>  [ 
1>   T=SomethingElse 
1>  ] 
1>[...](43) : error C2440: 'return' : cannot convert from 'Something *' to 'SomethingElse *' 
1>  Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast 

这个问题似乎是含糊不清,由于成员OBJ感从两个基地<东西>和基地< SomethingElse>继承,我可以解决它通过消除歧义我的电话给createBase:

Something* smth1 = d->Base<Something>::createBase<Something>(); 
SomethingElse* smth2 = d->Base<SomethingElse>::createBase<SomethingElse>(); 

然而,T他的解决方案非常不切实际,从句法上讲,我更喜欢更优雅的东西。而且,我对第一个错误信息感到困惑。这似乎意味着有一个实例化createBase < SomethingElse>在基地< Something>,但那又怎么可能?任何有关这个问题的信息或建议将不胜感激。

+0

这是不正确的编译器行为?我会说这应该导致模糊和编译错误。 – jpalecek 2010-05-20 22:22:02

+0

我对使用混合了继承的模板有些奇怪的感觉。无论如何,如果你想避免冗长的语法,使用'typedef'。 – 2010-05-20 22:25:21

回答

2

这似乎暗示在Base<Something>中有一个例示createBase<SomethingElse>,但这怎么可能呢?

有一定的,因为你的createBase<T>()是一个成员模板函数(在此功能的T无关,在周围的类做的T)。

我会做这样的事情:

// in Derived, or you could make some class (eg. MultiBase) for it 

template <class T> 
T* createBase() 
{ 
    return Base<T>::createBase(); 
} 
0

的这两种功能的“全名”是这样的:

template<class T> T* Derived::Base<Something>::createBase<T>(); 

据我所知,你的createBase()函数是一个模板函数在模板类中。从我所看到的,你想把`template`放在它的前面。

但是,这不应该完全解决您的问题,因为Derived然后(仍)具有Base<Something>::createBase()Base<SomethingElse>::createBase()

jpalecek的答案将完成解决问题的你,或者如果它是一个特定的基地,你可以访问对象:

Base<Something> * pBase = new Derived(); 
pBase->createBase(); 

static_cast<Base<Something> >(d)->createBase(); 

或者,要添加到jpalecek的答案,

static_cast<Base<T> >(this)->createBase(); 

应该工作,我认为是类型安全的;也就是说,如果this不是继承自Base<T>