Tri*_*dle 10 c++ pure-virtual undefined-behavior language-lawyer c++11
我确信我们都看到了由于导致调用纯虚函数的错误导致崩溃的代码.一个简单的例子是这样的:
struct Base
{
Base() { method(); }
virtual void method() = 0;
};
struct Derived : Base
{
void method() {};
};
int main()
{
Derived d;
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,该呼叫method()中的Base构造是专门引用为部分C++标准的10.4/6未定义的行为,所以这是毫不奇怪的是,我们最终崩溃.(g ++和Clang都警告过这一点,事实上,尽管Clang成功了,但是这个例子的链接失败了g ++.)
但是,只是为了好玩,任何人都能想出一种方法来调用一个不依赖于未定义行为的纯虚函数吗?
(我想你可以说,如果存在这样的方法,那么C++标准就有缺陷,但我只是好奇......)
编辑:几个答案的家伙,谢谢你,但我应该说清楚,我发现对一个纯虚函数进行非虚拟调用是合法的(提供一个定义存在于某处).我更想知道法律中是否有任何可能导致虚拟呼叫的聪明漏洞,因此很可能是在没有定义的常见情况下崩溃.
例如,也许通过多重继承,可以执行一些聪明的(合法的)强制转换,但最终会method()被称为"错误的"(未实现的)PV ,这种事情.我只是觉得这是一个有趣的脑力激荡器:-)
非虚拟地调用纯虚函数是完全合法的:
Derived d;
d.Base::method();
Run Code Online (Sandbox Code Playgroud)
当然,这需要定义函数,而在您的示例中并非如此.
取决于你的意思是可能的。这是编译成功的一个,但很可能会导致链接器错误:
struct Base
{
virtual void method() = 0;
};
struct Derived : Base
{
void method() { Base::method(); };
};
int main()
{
Derived d;
d.method();
}
Run Code Online (Sandbox Code Playgroud)
它可以编译,因为没有什么可以阻止纯虚函数实际上也具有函数体。这可以在同一翻译单元(在单独的定义中)或不同的翻译单元中提供。这就是为什么它是一个链接器错误而不是编译器错误 - 只是该函数在这里没有主体并不意味着它在其他地方没有主体。