简体   繁体   English

如果在编译时创建了vtable,为什么这个错误是链接器错误而不是编译错误?

[英]if vtable is created at compile time , why this error is an linker error and not compile error?

The following piece of code give me the error 以下代码给出了错误

undefined reference to `vtable for Derived' 未定义引用`vtable for Derived'

Code : 代码:

#include <iostream>
class base{
    public:
    base(){}
    virtual ~base(){}
    virtual void test()
    {
    }
};
class Derived:public base{
    public:
    Derived(){}
    ~Derived(){}  
    void test();
};
int main() {
    base* b = new Derived ();
    delete b;
}

which i understand is because the virtual fucntion test is declared but not defined in class Derived . 我理解的是因为虚拟fucntion test已声明但未在class Derived定义

But when i compile with g++ -c file.cpp which as per this C ompile or assemble the source files, but do not link . 但是当我使用g++ -c file.cpp进行编译时,根据这个 C ompile或汇编源文件,但不要链接 It does not give me any errors and compiles fine. 它没有给我任何错误和编译好。 Hence the above error is generated at linking time and not compile time. 因此,在链接时而非编译时生成上述错误。 From what i learned wasn't the vtable created at compile time. 从我学到的不是编译时创建的vtable Then why do i not get the error at compile time itself? 那为什么我不在编译时自己得到错误?

What I get with g++ foo.cpp -v 我用g++ foo.cpp -v得到了什么

/tmp/ccBc4VPu.o: In function `Derived::Derived()':
foo.cpp:(.text._ZN7DerivedC2Ev[_ZN7DerivedC5Ev]+0x1f): undefined reference to `vtable for Derived'
collect2: error: ld returned 1 exit status

That's a linker error, not a compiler error per se. 这是一个链接器错误,而不是编译器错误本身。

The root cause of the error is that test is declared in Derived, but not actually implemented. 错误的根本原因是test是在Derived中声明的,但实际上并未实现。 The linker is giving a confusing error message. 链接器给出了一个令人困惑的错误消息。 It should be declaring an error for the missing Derived::test method 应该为缺少的Derived::test方法声明一个错误

Compiler doesn't require to have all methods available. 编译器不要求所有方法都可用。 It's enough for him to have their declaration. 这对他来说已经足够了。

This method could be implemented in different compilation unit (cpp/cxx file) so for compiler it's not even possible to check if this method is available somewhere else. 此方法可以在不同的编译单元(cpp / cxx文件)中实现,因此对于编译器,甚至无法检查此方法是否在其他位置可用。 Compiler process one cpp file at time. 编译器处理一个cpp文件。

It's linker job to match methods and calls together. 它是将方法和调用匹配在一起的链接器作业。

However you formed the view that a vtable must be created at compile time, you are mistaken. 但是你形成了一个必须在编译时创建vtable的视图,你错了。

Separate compilation is a core concept in the standard. 单独编译是标准中的核心概念。 It is the reason that a compilation unit (aka source file) can compile, given any declaration of a function it needs - even if it doesn't have visibility of the definition. 这是编译单元(也称为源文件)可以编译的原因,给定它需要的任何函数声明 - 即使它没有定义的可见性。

In the typical "compile then link" build chain, this allows a compilation unit (source file) to compile, given any declaration of a function (member function or not) that might be defined in another compilation unit. 在典型的“编译然后链接”构建链中,这允许编译单元(源文件)在给定可能在另一个编译单元中定义的函数声明(成员函数与否)的情况下进行编译。

The absence of the definition of a function then needs to be detected by the linker. 然后,链接器需要检测缺少函数的定义。

Practically, this means that the compiler may emit information about the vtable, but it will be the linker that (ahem) links the specification of the vtable to the actual member functions. 实际上,这意味着编译器可能会发出有关vtable的信息,但是(ahem)链接器会将vtable的规范链接到实际的成员函数。

GCC has an FAQ entry for this problem: GCC有一个FAQ条目来解决这个问题:

When building C++, the linker says my constructors, destructors or virtual tables are undefined, but I defined them 在构建C ++时, 链接器说我的构造函数,析构函数或虚拟表是未定义的,但我定义了它们

The solution is to ensure that all virtual methods that are not pure are defined. 解决方案是确保定义所有非纯的虚方法。 Note that a destructor must be defined even if it is declared pure-virtual [class.dtor]/7. 请注意,即使声明为pure-virtual [class.dtor] / 7,也必须定义析构函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM