我正试图从一个旧类中派生出一个新类。基类声明如下所示:
class Driver : public Plugin, public CmdObject
{
protected:
Driver();
public:
static Driver* GetInstance();
virtual Engine& GetEngine();
public:
// Plugin methods...
virtual bool InitPlugin (Mgr* pMgr);
virtual bool Open();
virtual bool Close();
// CmdObject
virtual bool ExecObjCmd(uint16 cmdID, uint16 nbParams, CommandParam *pParams, CmdChannelError& error);
Mgr *m_pMgr;
protected:
Services *m_pServices;
Engine m_Engine;
};
它的构造函数如下所示:
Driver::Driver() :
YCmdObject("Driver", (CmdObjectType)100, true),
m_Engine("MyEngine")
{
Services *m_pServices = NULL;
Mgr *m_pMgr = NULL;
}
所以当我创建派生类时,我首先尝试简单地从基类继承:
class NewDriver : public Driver
并复制构造函数:
NewDriver::NewDriver() :
CmdObject("NewDriver", (EYCmdObjectType)100, true),
m_Engine("MyNewEngine")
{
Services *m_pServices = NULL;
Mgr *m_pMgr = NULL;
}
编译器(ADI公司的VisualDSP ++ 5.0)不喜欢这样:
".\NewDriver.cpp", line 10: cc0293: error: indirect nonvirtual base
class is not allowed
CmdObject("NewDriver", (EYCmdObjectType)100, true),
这是有道理的,所以我决定直接从Plugin和CmdObject继承。为了避免多重继承模糊问题(我想),我使用了虚拟继承:
class NewDriver : public Driver, public virtual Plugin, public virtual CmdObject
但是,在NewDriver中实现虚拟方法时,我尝试调用带有插件*的Mgr :: RegisterPlugin方法,我得到了这个:
".\NewDriver.cpp", line 89: cc0286: error: base class "Plugin" is
ambiguous
if (!m_pMgr->RegisterPlugin(this))
这个指针有多么模糊,如何解决?
谢谢,
- 保
答案 0 :(得分:4)
如果您派生自Driver
,则无需明确调用Driver
个基础的构造函数:
class NewDriver : public Driver { /* ... */ };
NewDriver::NewDriver() : Driver() {}
Driver
的构造函数然后初始化它自己的基础,你不必也不应该直接这样做。
如果它的行为应该不同,那么让它采取参数:
class Driver : /* ... */ {
public:
Driver(const std::string& name /* , ... */)
: CmdObject(name /* , ... */)
{}
// ...
};
NewDriver::NewDriver() : Driver("NewDriver" /* , ... */) {}
答案 1 :(得分:2)
多重继承的黄金法则 - 所有类的 ALL 公共基础必须是虚拟的。只要遵循该规则,多重继承就能正常工作。在您的情况下,您会收到不明确的基类错误,因为Plugin
中未声明virtual
Driver
答案 2 :(得分:1)
Georg有正确的答案,在这种情况下绝对不需要混淆多重继承。
使用multiple inheritance,尤其是创建dreaded diamond 强烈不鼓励,并且会给绝大多数C ++程序员带来很多困惑和挫折。< / p>
答案 3 :(得分:1)
如果您创建层次结构:
class A {public: a(int i){} };
class B : public A {public: b(){} };
class C : public B {public: c(); };
您不能直接从C的构造函数
将参数传递给A的构造函数C::C() : A(5) {} // illegal
除非A是B的虚拟基类,这是一种特殊情况,在这种情况下它很有用。请查看Tim Sylvester提供的链接。
编译器提到这种情况的事实并不意味着它是你的解决方案。
如果您在代码中创建了一个层次结构,则在Plugin
对象中有2个类型为CmdObject
的子对象和2个类型为NewDriver
的子对象。在这种情况下,如果您尝试将类型为this
的{{1}}指针向下转换为类型NewDriver*
,则编译器不知道如何调整地址,因为它不会知道指针应该指向你的Plugin*
对象中的2个子对象中的哪一个。这就是错误消息中提到的含糊不清的地方。有一种方法可以告诉编译器,但我认为我所描述的混乱应该说服你已经不是那样了。
答案 4 :(得分:0)
我不确定引入虚拟继承是你想要去的方式。你得到的初始错误是有效的 - 你试图从Driver类的“上方”调用CmdObject()ctor。你可以在Driver类中添加另一个ctor吗?
答案 5 :(得分:0)
如果您有某种理由希望再次从这些类继承,那么您不应该使用虚拟继承。如果要使用虚拟继承,则需要在更多基类上指定。但是,您不希望在此处使用虚拟继承。只需省略基类的初始化程序,因为Driver已经这样做了。在您的示例中,您根本不需要NewDriver构造函数,如果您的实现确实需要一个,那么它应仅用于初始化NewDriver的成员变量,它应该期望该驱动程序做对了。如果Driver没有做正确的事情,只需给它一个构造函数,该构造函数接受适当的参数并让构造函数做正确的事情。 E.g。
class Driver : public Stuff
{
public:
Driver(const char* enginename) : Stuff(99), m_Engine(enginename) { }
private:
Engine m_Engine;
};
class NewDriver : public Driver
{
public:
NewDriver() : Driver("New Driver!") { } // yes, Stuff gets initialized with 99 automatically!
};
答案 6 :(得分:0)
CmdObject
内的Driver
就足够了。调整Driver
以使protected
构造函数可以在指定限制内自定义CmdObject
。
class Driver ...
protected:
Driver( std::string driverName, std::string engineName );
...
Driver::Driver( std::string driverName, std::string engineName ) :
YCmdObject(driverName, (CmdObjectType)100, true),
m_Engine(engineName) {
...
NewDriver::NewDriver() :
Driver( "NewDriver", "MyNewEngine" ) {
...
}