为什么必须定义未使用的虚函数?

时间:2015-10-09 20:31:59

标签: c++ function virtual definition

我觉得很奇怪,与未使用的普通函数不同,仍然必须定义未使用的虚函数。我对在创建类对象时创建的隐式 vtables vpointers 有所了解 - 这有点回答了问题(必须定义函数以便指向可以定义虚函数)但这会进一步推动我的查询。

如果根本不可能调用虚函数,为什么需要为函数创建 vtable 条目?

class A{
    virtual bool test() const;
};

int main(){
    A a; //error: undefined reference to 'vtable for A'
}

即使我声明A::test()它从未在程序中使用过,但它仍然会引发错误。编译器是否可以不通过程序运行并且从未调用过test() - 因此不需要 vtable 条目?或者这对编译器来说是不合理的事情吗?

3 个答案:

答案 0 :(得分:6)

因为在编译器编写器上解决这个问题不可避免地是一个非常困难的问题,所以当能够保留虚函数未定义的有用性时,最好是可疑的。编译器作者肯定有更好的问题需要解决。

此外,即使您没有打电话,也正在使用该功能。你正在拿地址。

答案 1 :(得分:3)

OP说他已经知道vtable和vpointers,所以他知道未使用的虚函数和未使用的非虚函数之间存在差异:未使用的非虚函数不会在任何地方引用,而虚函数则是在类的vtable中至少引用一次。所以,基本上问题是问为什么编译器不够智能,如果没有在任何地方使用该函数,就不要在vtable中放置对虚函数的引用。这将使该功能也未定义。

编译器通常一次只能看到一个.cpp文件,所以它不知道你是否有一些调用该函数的源文件。

有些工具支持这种分析,他们称之为“全球”分析或类似的东西。您甚至可能会在某些编译器中找到它,并且可以通过某些编译器选项访问它。但它默认情况下从未启用,因为它会极大地降低编译速度。

事实上,你可以保留非虚函数未定义的原因也与缺乏全局分析有关,但是以不同的方式:如果编译器知道你已经省略了函数的定义,它可能至少会警告你。但由于它不进行全局分析,因此不能。事实证明,如果你尝试使用未定义的函数,编译器将不会捕获错误:它将被链接器捕获。

因此,只需定义一个包含ASSERT(FALSE)的空虚拟函数,然后继续生活。

答案 2 :(得分:0)

虚函数的重点在于可以通过基类指针调用它们。如果您从不使用基类虚函数,那么,为什么要定义它?如果使用它,它们必须离开父实现(如果它不是纯虚拟的),或者定义自己的实现,以便通过基类使用对象的代码实际上可以使用它。在这种情况下,使用函数,它只是不直接使用。

相关问题