c++ - 多个 vtables,在打电话时以错误的方式结束

标签 c++ multiple-inheritance diamond-problem

我有以下设置:

class CRpCat : 
    public CQueryDataBase,
    public IRpCat 
    {
public:
    CRpCat();
    virtual ~CRpCat();

// IRpCat
public:
    virtual HRESULT Initialize();

.....等等等等......

class CQueryDataBase : public CQueryNotify
{
    // this has virtual functions, all concrete
    virtual void OnDataChange(ULONG nRow, DBREASON eReason);

.....等等等等......

class CQueryNotify 
{
public:
    // abstract signatures
    virtual void OnDataChange(ULONG nRow, DBREASON eReason) = 0;

......等等............

最后

class IRpCat
{
public:
    virtual HRESULT Initialize() = 0;

所以,我有一个派生自 2 个类的类,并且到处都是虚函数。从派生的类不在一个父类下——这不是菱形问题(尽管可能与其相关)

问题来了。在实例化类并进行 Initialize() 调用时,我最终进入了 OnDataChange():

IRpCat *pCat = GetInstance()->GetRpCat();
pCat->Initialize();

Initialize() 和 OnDataChange() 都是它们各自 vtable 槽中的第一个函数——所以我不明白发生了什么,但我知道 Initialize() 调用是通过 vtable[0] 发生的——但不幸的是,我最终进入了错误的 vtable。凭直觉,我尝试了以下方法:

通过将第一行设为虚拟,我最终正确地进入了 Initialize()()

class CRpCat : 
       public virtual CQueryDataBase,
       public IRpCat 
       {

通过将第二行设为虚拟,我错误地结束了 OnDataChange()

class CRpCat : 
       public CQueryDataBase,
       public virtual IRpCat 
       {

并且通过将这两行都设为虚拟,在调用 Initialize() 时会抛出异常

class CRpCat : 
       public virtual CQueryDataBase,
       public virtual IRpCat 
       {

那么,有人可以解释一下这是怎么回事吗? (顺便说一下,这是 Visual Studio C++)。它肯定与 vtables 的布局方式有关。 谢谢

最佳答案

想通了。问题在于实例化对象的方式:

void * p = new CRpCat();
IRpCat * p2 = static_cast<IRpCat *>(p);
p2->Initialize();

首先将指针存储在“void *”中,然后再转换它,就是“切片”指针——因此会产生奇怪的结果。谢谢大家。

关于c++ - 多个 vtables,在打电话时以错误的方式结束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47061060/

相关文章:

c++ - 通过多重私有(private)继承扩展类——这是一回事吗?

c++ - 多重继承和多态问题

c++ - 使用带有多重继承的enable_shared_from_this

c++ - 多重继承的麻烦。如何调用基函数?

c++ - 菱形继承(钻石问题) (C++)

c++ - 为什么 ValueType 的 std::any & operator= 不是有条件的 noexcept?

c++ - OMP部分中的线程数

c++ - 自动进入 for 循环导致 "begin"未在此范围内声明

c++ - C++中的分号?

c++ - Derived1::Base 和 Derived2::Base 是否指代相同的类型?