5

我正在尝试重构一些代码,同时保留现有功能。我无法将指向对象的指针转换为基接口,然后再将派生类取出。在某些情况下,程序使用工厂对象来创建这些对象的实例。

以下是我正在使用的类的一些示例。

// 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

4 回答 4

10

您必须从 ISerializable虚拟继承(我刚刚使用 VS2010 对其进行了测试)。这是一个称为钻石问题的常见问题,编译器不知道要采用的层次结构路径。

编辑:

这应该这样做:

class NewAbstract : public virtual ISerializable { ... } 
class OldAbstract : public virtual ISerializable { ... } 
于 2010-05-25T16:41:04.703 回答
1

您可以通过首先投射到您的直接基地之一来绕过它,例如。

virtual ISerializable* createObject() const
{
    NewAbstract*const na = dynamic_cast< NewAbstract* >( new T() );
    return dynamic_cast< ISerializable* >( na );
}
于 2010-05-25T16:41:29.063 回答
0

不要从 NewAbstract 和 OldAbstract 虚拟继承。选择一个虚拟继承。我认为这可能会解决它。

于 2010-05-25T16:34:19.743 回答
-2

查找“可怕的钻石”和虚拟继承。他们可能会帮助你。

于 2010-05-25T16:31:47.613 回答