开发者

Can't cast a class with multiple inheritance

I am trying to refactor some code while leaving existing functionality in tact. I'm having trouble casting a pointer to an object into a base interface and then getting the derived class out later. The program uses a factory object to create instances of these objects in certain cases.

Here are some examples of the classes I'm working with.

// This is the one I'm working with now that is causing all the trouble.
// Some, but not all methods in NewAbstract an开发者_如何学Cd 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
    }
    ...
}

This question has good information on what the different types of casting do, but it's not helping me figure out this situation. Using static_cast and regular casting give me error C2594: 'static_cast': ambiguous conversions from 'MyObject *' to 'ISerializable *'. Using dynamic_cast causes createObject() to return NULL. The NormalObject style classes and the old version of MyObject work with the existing static_cast in the factory.

Is there a way to make this cast work? It seems like it should be possible.


You have to virtually inherit from ISerializable (I just tested it with VS2010). This is a common issue called the Diamond Problem, where the compiler does not know wich hierarchy path to take.

EDIT:

This should do it:

class NewAbstract : public virtual ISerializable { ... } 
class OldAbstract : public virtual ISerializable { ... } 


You can get round it by casting to one of your immediate bases first eg.

virtual ISerializable* createObject() const
{
    NewAbstract*const na = dynamic_cast< NewAbstract* >( new T() );
    return dynamic_cast< ISerializable* >( na );
}


Don't inherit virtually from both NewAbstract and OldAbstract. Pick one to inherit virtually from. I think that may take care of it.


Look up "dreaded diamond" and virtual inheritance. They may help you.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜