2010-05-11 99 views
3

我试图从旧的类中派生出新的类。基类的声明看起来是这样的:在C++中解析模糊的指针

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; 
} 

编译器(的VisualDSP ++ 5.0来自Analog Devices)不喜欢这样的:

".\NewDriver.cpp", line 10: cc0293: error: indirect nonvirtual base 
     class is not allowed 
CmdObject("NewDriver", (EYCmdObjectType)100, true), 

这很有道理,所以我决定直接从插件和CmdObject继承。为了避免多重继承歧义的问题(所以我认为),我用虚拟继承:

class NewDriver : public Driver, public virtual Plugin, public virtual CmdObject 

但随后,在NewDriver虚拟方法的实现,我试着拨打经理:: RegisterPlugin方法,它接受插件*,我得到了这个:

".\NewDriver.cpp", line 89: cc0286: error: base class "Plugin" is 
     ambiguous 
if (!m_pMgr->RegisterPlugin(this)) 

这个指针是如何模糊的,我该如何解决它?

感谢,

--Paul

回答

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" /* , ... */) {} 
+3

严格地说宣布virtual,如果基类构造函数不带任何参数,你甚至不需要把它在初始化列表,因为它将被默认自动构造。 – 2010-05-11 00:24:59

+0

@dash,这并不完全准确(至少不用g ++)。几乎继承的类型将在非虚拟继承类型之前初始化。因此,如果隐式顺序(来自物理继承层次)与物理顺序之间的初始化顺序不同,一些编译器至少会开始发布有关重新排列初始化顺序的警告(即使您省略了初始化列表并允许编译器做订单本身)。 – 2010-05-11 00:35:21

+0

我只是稍微改变了措辞,我不想在这里找到所有其他可能的错综复杂。 – 2010-05-11 00:45:13

0

我不能肯定,引入虚拟继承是你想在这里走的路。你得到的最初错误是有效的 - 你试图从Driver类的'上方'调用CmdObject()ctor。你可以添加另一个Ctor到Driver类吗?

1

Georg有正确的答案,在这种情况下肯定不需要混淆多重继承。

使用multiple inheritance,尤其是创造dreaded diamond强烈劝阻,并会导致混乱和挫折对于绝大多数的C++程序员很大。

0

如果您有某种原因希望再次从这些类继承,那么您不应该使用虚拟继承。如果你想使用虚拟继承,你需要在更多基类上指定它。但是,您不希望在此使用虚拟继承。因为Driver已经这样做了,所以省略基类的初始化程序。在你的例子中,你根本不需要一个NewDriver构造函数,如果你的实现实际上确实需要一个,那么它应该只有被用来初始化NewDriver的成员变量,并且它应该期望该Driver做正确的事情。如果Driver没有做正确的事情,只需给它一个构造函数,该构造函数接受适当的参数并让构造函数做正确的事情。例如。

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! 
}; 
0

CmdObjectDriver应该足够了。调整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") { 
    ... 
} 
1

如果您创建了一个层次:

class A {public: a(int i){} }; 
class B : public A {public: b(){} }; 
class C : public B {public: c(); }; 

你不能将参数传递给A的构造直接构成C的构造函数

C::C() : A(5) {} // illegal 

除非A是B的虚拟基类,这是一种特殊情况,在这种情况下它是有用的。请检查Tim Sylvester提供的链接。

事实上,编译器提到这种情况并不意味着它是您的解决方案。

如果您在您的代码中创建了一个层次结构,那么您的NewDriver对象中有2个Plugin子对象和2个子对象CmdObject。在这种情况下,如果您尝试将类型为NewDriver*this指针向下翻录为Plugin*类型,则编译器不知道如何调整地址,因为它不知道您的NewDriver对象中存在哪个子对象该指针应该指向。这就是错误信息中提到的歧义之处。有一种方法可以告诉编译器,但我认为我描述的混乱应该说服你已经不是这样了。

1

多重继承的金科玉律 - ALLMUST的ALL公共基础是虚拟的。只要你遵循这个规则,多重继承就可以正常工作。在你的情况,你得到的暧昧基类错误,因为PluginDriver