【问题标题】:Multiple inheritance from template class模板类的多重继承
【发布时间】:2010-05-20 22:17:56
【问题描述】:

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

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 和 Base 继承的,因此问题似乎是模棱两可的,我可以通过消除对 createBase 的调用的歧义来解决这个问题:

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

但是,从语法上讲,这种解决方案非常不切实际,我更喜欢更优雅的解决方案。此外,我对第一条错误消息感到困惑。这似乎暗示在 Base 中有一个实例化 createBase,但这怎么可能呢?任何有关此问题的信息或建议将不胜感激。

【问题讨论】:

  • 这甚至是正确的编译器行为吗?我会说这会导致歧义和编译错误。
  • 我对使用与继承混合的模板有一些奇怪的感觉。无论如何,如果您想避免冗长的语法,请使用typedef

标签: c++ inheritance templates multiple-inheritance


【解决方案1】:

这似乎暗示createBase&lt; SomethingElse &gt;Base&lt; Something &gt; 中有一个实例化,但这怎么可能呢?

肯定有,因为您的createBase&lt;T&gt;() 是成员模板函数(并且此函数中的T 与周围类中的T 无关)。

我会这样做:

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

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

【讨论】:

    【解决方案2】:

    这两个函数的“全名”是这样的:

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

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

    但是,这不应该完全解决您的问题,因为 Derived 将(仍然)同时拥有 Base&lt;Something&gt;::createBase()Base&lt;SomethingElse&gt;::createBase()

    jpalecek 的回答将为您完成解决问题,或者您可以像访问特定基础一样访问该对象:

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

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

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

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

    应该可以工作,而且我认为是类型安全的;也就是说,如果this 不是从Base&lt;T&gt; 继承,则不会工作

    【讨论】:

      猜你喜欢
      • 2011-03-22
      • 2018-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多