Множественное наследование от класса шаблона - PullRequest
3 голосов
/ 21 мая 2010

У меня проблемы с множественным наследованием от разных экземпляров одного и того же шаблонного класса. Конкретно я пытаюсь сделать это:

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 , но как это вообще возможно? Любая информация или советы по этому вопросу будет принята с благодарностью.

Ответы [ 2 ]

2 голосов
/ 21 мая 2010

Кажется, подразумевается, что в 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 голосов
/ 21 мая 2010

«Полные имена» обеих функций примерно такие:

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>

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...