从模板类进行多重继承

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从Base< Something >和Base< SomethingElse >继承而来的二义性,我可以通过消除对createBase的调用二义性来解决它。
Something* smth1 = d->Base<Something>::createBase<Something>();
SomethingElse* smth2 = d->Base<SomethingElse>::createBase<SomethingElse>();

然而,从语法的角度来看,这个解决方案非常不切实际,我更希望有更优雅的方法。此外,我对第一个错误信息感到困惑。它似乎暗示在Base 中存在一个createBase 的实例化,但这怎么可能呢?非常感谢您对此问题提供任何信息或建议。

这是正确的编译器行为吗?我认为这应该导致歧义和编译错误。 - jpalecek
我对使用模板和继承混合的方法有些奇怪的感觉。无论如何,如果你想避免冗长的语法,可以使用 typedef - Xavier Ho
2个回答

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>,那么它将无法正常工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接