c++ 链接器错误未定义对 vtable 的引用

问题描述 投票:0回答:3

我正在尝试编写一个小型的C++继承程序,它将包含虚函数、头文件和3个类,A、B:A、C:B,编译成功后,链接器在派生类的派生中失败, C.o,声明

relocation against `_ZTV26C' in read-only section `.text'

undefined reference to `vtable for C'

有人能看到我错过了什么吗?

啊啊

#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;
}

主.cpp

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

确切的make命令,以及错误消息: make all 构建目标:demo_proj 调用:GCC C++ 链接器 g++ -o "ass5_demo" ./A.o ./B.o ./C.o ./main.o /usr/bin/ld: ./main.o: 警告:针对 _ZTV1C' 重定位在只读部分 .text._ZN1CC2ENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE[_ZN1CC5ENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE]' /usr/bin/ld: ./main.o: 在函数 C::C(std::__cxx11::basic_string )': /home/some_user/eclipse -workspace/demo_proj/../C.h:14:对 C'/usr/bin/ld 的 vtable 的未定义引用:警告:在 PIE 中创建 DT_TEXTREL

c++ inheritance
3个回答
3
投票

经过几个小时的调试和无数次的尝试,我找到了答案,并出现相同的错误消息。 这是 C++ 链接器的一种不正当方式,告诉我我的一个类中有一个未实现的方法。 添加到 c.h

bool derivedTest() override;

和c.cpp

bool C::derivedTest(){return false;}

p.s 发现问题的另一种好方法是在头文件中的每条消息后添加覆盖,编译器更清晰


1
投票

我遇到这个问题是因为我忘记将 .cpp 文件添加到我的 makefile 中。


0
投票

这个建议是针对 GCC 的:

GCC 是一个很好的编译器,但不会“说英语”:错误消息对于初次使用的用户来说是非常令人困惑的。

因此我的解决方案是为 GCC 和 LLVM 配置一个项目;如果发生神秘错误,请使用 LLVM (clang) 重新编译。

PS 如果你问我为什么不总是使用 clang,答案是它 - 对于 my 使用 - 大约慢 10%。

© www.soinside.com 2019 - 2024. All rights reserved.