由于CBase具有纯虚函数,我无法创建它的实例。 在这种情况下,如何通过'novtable'生成违规? 如果没办法,那么“novtable”是否应该应用于所有抽象类?
此代码段中没有违规行为:
struct __declspec(novtable) CBase
{
virtual void f() = 0;
};
struct CSub: public CBase
{
CSub() { this->f(); }
void f() { printf("inside CSub::f()"); }
};
void TestVTable()
{
CBase* pBase = new CSub();
pBase->f();
}
答案 0 :(得分:2)
要违反此规定,您需要“调用”虚拟机制。
首先,应该动态创建对象,否则将被调用的函数是在对象类中定义的函数。在这种情况下 - 肯定会是CBase::f()
,所以不需要访问虚拟表。
第二,你需要显式调用该函数,因为如果调用来自构造函数,f
在编译时被“解析”,因为它是肯定的,被调用的f
函数将是CBase::f()
。所以,再次 - 这里没有必要访问虚拟表。
因此,例如,要违反此规定,您需要“使用”虚拟机制,例如:
void TestVTable()
{
CBase* Base = new CBase();
Base->f();
}
答案 1 :(得分:1)
我发现生成违规行为的唯一方法如下所示。 这里有两把钥匙: 1.必须在基础构造函数中调用f() 2.'这个'必须是铸造的。 这很难,因为抽象类没有实例(它本身,而不是它的子类)。
struct __declspec(novtable) CBase
{
CBase()
{
((CBase*)this)->f();
};
virtual void f() = 0;
};
struct CSub: public CBase
{
void f() { }
};
void TestVTable()
{
CSub();
}
答案 2 :(得分:0)
虚拟成员不必是抽象的 - 非抽象的。
struct __declspec(novtable) Struct
{
virtual void DoStuff() {}
};
int _tmain(int /*argc*/, _TCHAR* /*argv[]*/)
{
Struct* object = new Struct();
object->DoStuff(); // crashes here
}
novtable
的重点是当它应用于class X
时,class X
的构造函数不会将vtable指针设置为class X
&#39}虚函数表。这就是全部。因此,在使用class X
declspec在novtable
上调用虚拟方法时,任何情况下都会发生崩溃,这样class Base
没有novtable
declspec class X
1}}继承自,它将具有与被调用者相同的虚拟成员函数。如果存在这样的class Base
,则可能会调用错误的(不是大多数派生的)成员函数。如果不存在这样的类,则会发生崩溃。