Я пытаюсь осуществить рефакторинг некоторый код при отъезде существующей функциональности в такте. Я испытываю затруднения при кастинге указателя на объект в основной интерфейс и затем выводе производного класса позже. Программа использует объект фабрики для создания экземпляров этих объектов в определенных случаях.
Вот некоторые примеры классов, с которыми я работаю.
// 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 Factory
{
public:
...
virtual ISerializable* createObject() const
{
return static_cast(new T()); // current factory code
}
...
}
Этот вопрос имеет хорошую информацию о том, что делают различные типы кастинга, но это не помогает мне выяснить эту ситуацию. Используя static_cast и регулярный кастинг дают мне error C2594: 'static_cast': ambiguous conversions from 'MyObject *' to 'ISerializable *'
. Используя dynamic_cast заставляет createObject () возвращать ПУСТОЙ УКАЗАТЕЛЬ. NormalObject разрабатывают классы и старую версию работы MyObject с существующим static_cast на фабрике.
Существует ли способ заставить этот бросок работать? Кажется, что это должно быть возможно.
Вы должны виртуально унаследовать от ISerializable (я только что тестировал его с VS2010). Это обычная проблема, называемая Алмазная проблема , когда компилятор не знает, какой иерархический путь выбрать.
РЕДАКТИРОВАТЬ:
Это должно сработать:
class NewAbstract : public virtual ISerializable { ... }
class OldAbstract : public virtual ISerializable { ... }
Вы можете обойти это, применив сначала к одной из ваших непосредственных баз, например.
virtual ISerializable* createObject() const
{
NewAbstract*const na = dynamic_cast< NewAbstract* >( new T() );
return dynamic_cast< ISerializable* >( na );
}
Найдите «ужасный алмаз» и виртуальное наследование. Они могут вам помочь.
Не наследуют виртуально и от NewAbstract, и от OldAbstract. Выберите тот, от которого хотите унаследовать виртуально. Я думаю, что это может решить эту проблему.