Не могу привести класс с множественным наследованием - PullRequest
5 голосов
/ 25 мая 2010

Я пытаюсь провести рефакторинг некоторого кода, оставляя существующую функциональность в такте. У меня возникли проблемы с приведением указателя на объект в базовый интерфейс и последующим выводом производного класса. Программа использует фабричный объект для создания экземпляров этих объектов в определенных случаях.

Вот несколько примеров классов, с которыми я работаю.

// This is the one I'm working with now that is causing all the trouble.
// Some, but not all methods in NewAbstract and OldAbstract overlap, so I
// used virtual inheritance.
class MyObject : virtual public NewAbstract, virtual public OldAbstract { ... }

// This is what it looked like before
class MyObject : public OldAbstract { ... }

// This is an example of most other classes that use the base interface
class NormalObject : public ISerializable

// The two abstract classes. They inherit from the same object.
class NewAbstract : public ISerializable { ... }
class OldAbstract : public ISerializable { ... }

// A factory object used to create instances of ISerializable objects.
template<class T> class Factory
{
public:
    ...
    virtual ISerializable* createObject() const
    {
        return static_cast<ISerializable*>(new T()); // current factory code
    }
    ...
}

Этот вопрос содержит хорошую информацию о том, что делают разные типы кастинга, но это не помогает мне разобраться в этой ситуации. Использование static_cast и обычного приведения дает мне error C2594: 'static_cast': ambiguous conversions from 'MyObject *' to 'ISerializable *'. Использование dynamic_cast приводит к тому, что createObject () возвращает NULL. Классы стилей NormalObject и старая версия MyObject работают с существующим static_cast на заводе.

Есть ли способ заставить этот актерский состав работать? Кажется, это должно быть возможно.

Ответы [ 4 ]

10 голосов
/ 25 мая 2010

Вы должны фактически наследовать от ISerializable (я только что проверил это с VS2010). Это общая проблема, называемая Diamond Problem , где компилятор не знает, какой путь иерархии выбрать.

EDIT:

Это должно сделать это:

class NewAbstract : public virtual ISerializable { ... } 
class OldAbstract : public virtual ISerializable { ... } 
1 голос
/ 25 мая 2010

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

virtual ISerializable* createObject() const
{
    NewAbstract*const na = dynamic_cast< NewAbstract* >( new T() );
    return dynamic_cast< ISerializable* >( na );
}
0 голосов
/ 25 мая 2010

Не наследуйте виртуально от NewAbstract и OldAbstract. Выберите один, чтобы наследовать практически от. Я думаю, что это может позаботиться об этом.

0 голосов
/ 25 мая 2010

Ищите «страшный бриллиант» и виртуальное наследство. Они могут вам помочь.

...