gpt4 book ai didi

c++ - clang:没有外联虚方法定义(纯抽象 C++ 类)

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:47:10 24 4
gpt4 key购买 nike

我正在尝试使用 Clang-3.5 编译以下简单的 C++ 代码:

测试.h:

class A
{
public:
A();
virtual ~A() = 0;
};

测试.cc:

#include "test.h"

A::A() {;}
A::~A() {;}

我用于编译的命令(Linux,uname -r: 3.16.0-4-amd64):

$clang-3.5 -Weverything -std=c++11 -c test.cc

我得到的错误:

./test.h:1:7: warning: 'A' has no out-of-line virtual method definitions; its vtable will be emitted in every translation unit [-Wweak-vtables]

有什么提示为什么会发出警告吗?虚拟析构函数根本没有内联。恰恰相反,test.cc 中提供了一个外联定义。我在这里缺少什么?

编辑

我不认为这个问题是重复的: What is the meaning of clang's -Wweak-vtables?正如 Filip Roséen 所建议的那样。在我的问题中,我特别提到了纯抽象类(在建议的拷贝中未提及)。我知道 -Wweak-vtables 如何与非抽象类一起工作,我对此很满意。在我的示例中,我在实现文件中定义了析构函数(纯抽象)。这应该可以防止 Clang 发出任何错误,即使使用 -Wweak-vtables

最佳答案

我们不想将 vtable 放在每个翻译单元中。所以必须有一些翻译单元的顺序,这样我们就可以说,我们将 vtable 放在“第一个”翻译单元中。如果此顺序未定义,我们会发出警告。

您可以在 Itanium CXX ABI 中找到答案.在有关虚拟表 (5.2.3) 的部分中,您会发现:

The virtual table for a class is emitted in the same object containing the definition of its key function, i.e. the first non-pure virtual function that is not inline at the point of class definition. If there is no key function, it is emitted everywhere used. The emitted virtual table includes the full virtual table group for the class, any new construction virtual tables required for subobjects, and the VTT for the class. They are emitted in a COMDAT group, with the virtual table mangled name as the identifying symbol. Note that if the key function is not declared inline in the class definition, but its definition later is always declared inline, it will be emitted in every object containing the definition.
NOTE: In the abstract, a pure virtual destructor could be used as the key function, as it must be defined even though it is pure. However, the ABI committee did not realize this fact until after the specification of key function was complete; therefore a pure virtual destructor cannot be the key function.

第二部分是对您问题的回答。纯虚拟析构函数不是关键函数。因此,不清楚该把vtable放在哪里,到处都是。结果我们收到了警告。

您甚至可以在 Clang source documentation 中找到此解释.

特别针对警告:当所有虚拟函数都属于以下类别之一时,您将收到警告:

  1. inline 在类定义中为 A::x() 指定。

    struct A {
    inline virtual void x();
    virtual ~A() {
    }
    };
    void A::x() {
    }
  2. B::x() 在类定义中是内联的。

    struct B {
    virtual void x() {
    }
    virtual ~B() {
    }
    };
  3. C::x() 是纯虚拟的

    struct C {
    virtual void x() = 0;
    virtual ~C() {
    }
    };
  4. (属于3。)你有一个纯虚析构函数

    struct D {
    virtual ~D() = 0;
    };
    D::~D() {
    }

    在这种情况下,可以定义顺序,因为必须定义析构函数,但是,根据定义,仍然没有“第一个”翻译单元。

对于所有其他情况,关键函数是第一个不属于这些类别的虚拟函数,并且 vtable 将放置在定义关键函数的翻译单元中。

关于c++ - clang:没有外联虚方法定义(纯抽象 C++ 类),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40138362/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com