我有以下设置:
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/