You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++继承程序链接报错:undefined reference to vtable for C

三层C++继承程序链接报错:undefined reference to `vtable for C'

问题场景

我正在编写一个三层继承的C++程序,类结构为A基类,B继承A,C继承B,包含虚函数和分离的头文件实现。编译所有源文件成功,但链接阶段报错,提示找不到C类的虚函数表。

报错核心信息:

relocation against `_ZTV1C' in read-only section `.text'
undefined reference to `vtable for C'

完整代码

A.h

#ifndef A_H_
#define A_H_
#include <string>
#include <iostream>
using namespace std;

class A {
protected:
    string name;
public:
    A(string name);
    virtual ~A();
    virtual void justATest(){}
    void justBecause();
    virtual bool derivedTest(){}
};

#endif /* A_H_ */

A.cpp

#include "A.h"

A::A(string name) {this->name.assign(name);}

A::~A() {}

void A::justBecause(){}

B.h

#ifndef B_H_
#define B_H_
#include "A.h"
#include <string>

class B : public A{
public:
    B(string name):A(name){}
    virtual ~B(){}
    bool derivedTest();
};

#endif /* B_H_ */

B.cpp

#include "B.h"
bool B::derivedTest()
{
    return true;
}

C.h

#ifndef C_H_
#define C_H_
#include "B.h"

class C : public B{
public:
    C(string name) :B(name){}
    virtual ~C(){}
    void justATest();
};

#endif /* C_H_ */

C.cpp

#include "C.h"
void C::justATest()
{
    cout<< this->name;
}

main.cpp

#include "C.h"
int main(int argc, char* argv[]) {
    C* c = new C("str");
return 0;
}

编译命令及错误详情

编译命令:

make all

完整错误输出:

Building target: demo_proj
Invoking: GCC C++ Linker
g++ -o "ass5_demo" ./A.o ./B.o ./C.o ./main.o
/usr/bin/ld: ./main.o: warning: relocation against `_ZTV1C' in read-only section `.text._ZN1CC2ENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE[_ZN1CC5ENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE]'
/usr/bin/ld: ./main.o: in function `C::C(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)':
/home/some_user/eclipse-workspace/demo_proj/../C.h:14: undefined reference to `vtable for C'
/usr/bin/ld: warning: creating DT_TEXTREL in a PIE

问题原因及解决方法

原因

GCC编译器下,当类包含非内联的虚函数(比如C::justATest()),同时将另一个虚函数(这里是析构函数~C())在头文件中内联定义时,编译器无法正确确定该类虚函数表(vtable)的生成位置。通常编译器会在包含类第一个非内联虚函数定义的编译单元中生成vtable,但内联析构函数会干扰这一逻辑,导致C.cpp中没有生成vtable,链接时其他编译单元找不到它。

解决方法

方法一:将C类的析构函数移到C.cpp中实现

修改C.h中的析构函数声明,只保留声明不定义:

class C : public B{
public:
    C(string name) :B(name){}
    virtual ~C(); // 移除内联定义
    void justATest();
};

在C.cpp中添加析构函数的实现:

#include "C.h"
void C::justATest()
{
    cout<< this->name;
}

C::~C() {} // 添加析构函数实现

方法二:确保C类有一个内联的纯虚函数(可选)

在C类中添加一个内联的纯虚函数(比如空的虚函数),不过这种方法不如第一种规范,更推荐方法一。

修改后重新编译链接,即可解决报错。

内容的提问来源于stack exchange,提问作者MichaelK

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 00:01:29