4

我正在尝试从旧类派生一个新类。基类声明如下所示:

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

编译器(来自 Analog Devices 的 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 中实现虚拟方法时,我尝试调用采用 Plugin* 的 Mgr::RegisterPlugin 方法,结果如下:

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

this 指针如何模棱两可,我该如何解决?

谢谢,

——保罗

4

7 回答 7

4

如果您从 派生Driver,则不必Driver显式调用 s 基的构造函数:

class NewDriver : public Driver { /* ... */ };
NewDriver::NewDriver() : Driver() {}

then的构造函数Driver初始化它自己的基础,你不必也不应该直接这样做。
如果它应该表现不同,让它接受参数:

class Driver : /* ... */ {
public:
    Driver(const std::string& name /* , ... */)
      : CmdObject(name /* , ... */)
    {}
    // ...
};

NewDriver::NewDriver() : Driver("NewDriver" /* , ... */) {}
于 2010-05-11T00:17:26.730 回答
2

多重继承的黄金法则——所有类的所有公共基础都必须是虚拟的。只要您遵循该规则,多重继承就会正常工作。在您的情况下,您会收到模棱两可的基类错误,因为未在PluginvirtualDriver

于 2010-05-11T01:15:25.007 回答
1

Georg 有正确答案,在这种情况下,绝对没有必要搞乱多重继承。

强烈建议不要使用多重继承,尤其是创建可怕的菱形,这会给绝大多数 C++ 程序员带来极大的困惑和挫败感。

于 2010-05-11T00:24:49.857 回答
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 提供的链接。

编译器提到这种情况并不意味着它是你的解决方案。

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

于 2010-05-11T00:39:35.147 回答
0

我不确定引入虚拟继承是您想要的方式。您得到的初始错误是有效的 - 您正在尝试从 Driver 类的“上方”调用 CmdObject() ctor。您可以在 Driver 类中添加另一个 ctor 吗?

于 2010-05-11T00:18:18.280 回答
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!
};
于 2010-05-11T00:29:32.337 回答
0

内部应该足够CmdObject了。Driver调整Driver以拥有一个可以在指定范围内protected自定义的构造函数。CmdObject

class Driver ...
protected:
    Driver( std::string driverName, std::string engineName );

…</p>

Driver::Driver( std::string driverName, std::string engineName ) :
    YCmdObject(driverName, (CmdObjectType)100, true),
    m_Engine(engineName) {

…</p>

NewDriver::NewDriver() : 
    Driver( "NewDriver", "MyNewEngine" ) {
    ...
}
于 2010-05-11T00:30:55.367 回答