如何在MSVC中生成由'novtable'引起的违规?

时间:2011-11-20 22:14:39

标签: c++

由于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(); 
}

3 个答案:

答案 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,则可能会调用错误的(不是大多数派生的)成员函数。如果不存在这样的类,则会发生崩溃。