我有以下设置:
class CRpCat :
public CQueryDataBase,
public IRpCat
{
public:
CRpCat();
virtual ~CRpCat();
// IRpCat
public:
virtual HRESULT Initialize();
..... blah blah .......
class CQueryDataBase : public CQueryNotify
{
// this has virtual functions, all concrete
virtual void OnDataChange(ULONG nRow, DBREASON eReason);
..... blah blah .......
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插槽中的第一个函数 - 所以我不明白发生了什么,但我得到的是通过vtable [0]发生的Initialize()调用 - 但不幸的是,我最终在错误的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 ++)。它绝对与vtable的布局方式有关。 谢谢
答案 0 :(得分:1)
想出来。问题是对象实例化的方式:
void * p = new CRpCat();
IRpCat * p2 = static_cast<IRpCat *>(p);
p2->Initialize();
首先将指针存储在“void *”中,然后将其转换为“切片”指针 - 因此产生了奇怪的结果。谢谢大家。