解决 C++ 中不明确的 this 指针
我正在尝试从旧类中派生出一个新类。基类声明如下所示:
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 指针如何不明确,如何解决?
谢谢,
--保罗
I'm trying to derive a new class from an old one. The base class declaration looks like this:
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;
};
Its constructor looks like this:
Driver::Driver() :
YCmdObject("Driver", (CmdObjectType)100, true),
m_Engine("MyEngine")
{
Services *m_pServices = NULL;
Mgr *m_pMgr = NULL;
}
So when I created my derived class, I first tried to simply inherit from the base class:
class NewDriver : public Driver
and copy the constructor:
NewDriver::NewDriver() :
CmdObject("NewDriver", (EYCmdObjectType)100, true),
m_Engine("MyNewEngine")
{
Services *m_pServices = NULL;
Mgr *m_pMgr = NULL;
}
The compiler (VisualDSP++ 5.0 from Analog Devices) didn't like this:
".\NewDriver.cpp", line 10: cc0293: error: indirect nonvirtual base
class is not allowed
CmdObject("NewDriver", (EYCmdObjectType)100, true),
That made sense, so I decided to directly inherit from Plugin and CmdObject. To avoid multiple inheritance ambiguity problems (so I thought), I used virtual inheritance:
class NewDriver : public Driver, public virtual Plugin, public virtual CmdObject
But then, in the implementation of a virtual method in NewDriver, I tried to call the Mgr::RegisterPlugin method that takes a Plugin*, and I got this:
".\NewDriver.cpp", line 89: cc0286: error: base class "Plugin" is
ambiguous
if (!m_pMgr->RegisterPlugin(this))
How is the this pointer ambiguous, and how do I resolve it?
Thanks,
--Paul
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
如果您从
Driver
派生,则不必显式调用Driver
基类的构造函数:Driver
的构造函数然后初始化其自己的构造函数基地,你不必也不应该直接这样做。如果它的行为不同,请让它接受参数:
If you derive from
Driver
, you don't have to call the constructors ofDriver
s bases explicitly:The constructor of
Driver
then initializes its own bases, you don't have to and shouldn't do that directly.If it should behave differently, let it take parameters:
多重继承的黄金法则——所有类的所有公共基必须是虚拟的。只要遵循该规则,多重继承就能正常工作。在您的情况下,您会收到不明确的基类错误,因为
Plugin
未在Driver
中声明virtual
The golden rule of multiple inheritance -- ALL public bases of ALL classes MUST be virtual. As long as you follow that rule, multiple inheritance will work properly. In your case, you're getting the ambiguous base class errors because
Plugin
is not declaredvirtual
inDriver
Georg 的答案是正确的,在这种情况下绝对没有必要搞乱多重继承。
使用多重继承,尤其是创建可怕的钻石是强烈< /strong> 气馁,并且会给绝大多数 C++ 程序员带来很大的困惑和沮丧。
Georg has the correct answer, there is definitely no need to mess with multiple inheritance in this case.
Using multiple inheritance, especially to create the dreaded diamond is strongly discouraged, and will lead to a great deal of confusion and frustration for the vast majority of C++ programmers.
如果您创建层次结构:
您不能直接从 C 的构造函数将参数传递给 A 的构造函数,
除非 A 是 B 的虚拟基类,这是一种特殊情况,在这种情况下它很有用。请检查蒂姆·西尔维斯特提供的链接。
编译器提到这种情况并不意味着它是适合您的解决方案。
如果您创建像代码中那样的层次结构,则
NewDriver
对象中有 2 个Plugin
类型的子对象和 2 个CmdObject
类型的子对象。在这种情况下,如果您尝试将NewDriver*
类型的this
指针向下转换为Plugin*
类型,编译器将不知道如何调整地址,因为它不知道指针应该指向NewDriver
对象中存在的 2 个子对象中的哪一个。这就是错误消息中提到的歧义所在。有一种方法可以告诉编译器,但我认为我所描述的混乱应该已经让你相信这不是方法。If You create a hierarchy:
You can't pass arguments to the A's constructor directly form the C's constructor
unless A is a virtual base class of B which is a special case and in this case it is useful. Please check the links provided by Tim Sylvester.
The fact that the compiler mentions this case doesn't mean it's a solution for You.
If You create a hierarchy like in Your code, You have 2 subobjects of type
Plugin
and 2 subobject of typeCmdObject
in YourNewDriver
object. In this case, if You try to downcast thethis
pointer of typeNewDriver*
for example to the typePlugin*
, the compiler has no idea how to adjust the address, because it doesn't know to which of the 2 subobjects present in YourNewDriver
object that pointer is supposed to point to. That's where the ambiguity mentioned in the error message comes form. There is a way to tell the compiler, but I think the mess I'm describing should convince You already that is not the way.我不确定引入虚拟继承是您想要的方式。您收到的初始错误是有效的 - 您试图从 Driver 类的“上方”调用 CmdObject() ctor。您可以在 Driver 类中添加另一个 ctor 吗?
I'm not certain that introducing Virtual Inheritance is the way you want to go here. The initial error you got was valid - you're trying to invoke the CmdObject() ctor from 'above' the Driver class. Can you add another ctor to the Driver class?
如果您出于某种原因想要再次从这些类继承,那么您不应该使用虚拟继承。如果要使用虚拟继承,则需要在更基类上指定。但是,您不想在这里使用虚拟继承。只需省略基类的初始化程序,因为 Driver 已经这样做了。在您的示例中,您根本不需要 NewDriver 构造函数,并且如果您的实现确实需要一个构造函数,那么它应该仅用于初始化 NewDriver 的成员变量,并且应该期望 Driver做正确的事。如果 Driver 没有做正确的事情,只需给它一个带有适当参数的构造函数,并让该构造函数做正确的事情。例如
If you had some reason for wanting to inherit from those classes again, then you shouldn't use virtual inheritance. If you want to use virtual inheritance, you need to specify that on the more-base classes. However, you don't want to use virtual inheritance here. Just leave out the initializer of the base classes, since Driver is already doing that. In your example, you don't need a NewDriver constructor at all, and if your implementation actually does need one, then it should only be used to initialize the member variables of NewDriver and it should expect that Driver does the right thing. If Driver does not do the right thing, just give it a constructor that takes appropriate parameters and have that constructor do the right thing. E.g.
Driver
中的CmdObject
应该足够了。调整Driver
以拥有一个protected
构造函数,该构造函数可以在指定限制内自定义CmdObject
。……
The
CmdObject
withinDriver
should be sufficient. AdjustDriver
to have aprotected
constructor which can customize theCmdObject
within specified limits.…
…