C++基类非虚函数调用纯虚函数引发Clang链接错误咨询
解析Clang链接错误的原因与解决方案
哈哈,这个问题我之前也踩过一模一样的坑!你困惑的点刚好戳中了C++里纯虚析构函数的一个极易被忽略的特殊规则——纯虚析构函数必须提供定义,这和普通纯虚函数的规则完全不一样。
先还原你的代码场景(根据描述推测)
我猜你的代码大概是这样的:
class Base { public: // 纯虚函数 virtual void foo() = 0; // 调用纯虚函数的普通成员函数 void bar() { foo(); } // 声明为纯虚的析构函数,但没有定义 virtual ~Base() = 0; }; class Child : public Base { public: // 实现纯虚函数foo void foo() override { // 你的业务逻辑 } ~Child() override = default; }; int main() { Child c; c.bar(); // 调用基类的bar函数 return 0; }
为什么会出现链接错误?
你可能以为问题出在bar()调用纯虚函数foo()上,但其实这部分是完全合法的——因为当你调用c.bar()时,Child对象已经完全构造完成,虚函数表已经正确指向Child的foo实现,这时候调用foo()不会有任何问题。
真正的问题出在对象销毁阶段:当main函数执行完毕,Child对象c会被销毁。C++的析构函数调用链是从最派生类到基类,所以会先调用Child的析构函数,然后自动调用Base的析构函数。而你把Base的析构函数声明为纯虚函数,却没有给它提供定义,链接器找不到这个函数的实现,于是就抛出了链接错误。
这里要纠正你开头的一个误解:你说“无法定义纯虚析构函数”,这是错误的!C++标准明确要求,纯虚析构函数必须有定义——因为派生类的析构一定会调用它,这是纯虚函数里的特例,普通纯虚函数可以不用定义(除非你要显式调用它),但纯虚析构不行。
解决方案
给Base的纯虚析构函数添加一个空定义即可:
// 在类外定义纯虚析构函数 Base::~Base() {}
这样链接器就能找到析构函数的实现,错误就会消失。
额外补充
如果你的代码里Base的析构函数不是纯虚的,那编译器会自动生成一个隐式定义的析构函数,就不会有这个问题。但一旦你把它声明为纯虚,就必须手动提供定义。
内容的提问来源于stack exchange,提问作者koreus737
相关产品推荐
相关产品推荐

