gpt4 book ai didi

c++ - 全特化模板类没有外线虚方法定义

转载 作者:塔克拉玛干 更新时间:2023-11-03 08:21:04 24 4
gpt4 key购买 nike

我有这样的结构:

静态库 A

interface.h

class Interface
{
public:
virtual ~Interface() // no pure virtual dtor

virtual void pureMethod1() = 0;
virtual void pureMethod2() = 0;

virtual void virtualMethod1();
virtual void virtualMethod2();
};

interface.cpp

include "interface.h"
Interface::~Interface() = default;
Interface::virtualMethod1() {}
Interface::virtualMethod2() {}

使用 A 的静态库 B

BaseT.h

#include "interface.h"
template<class T>
class BaseT final : public Interface
{
static_assert(false, "can't use this specialization");
};

specialized1.h

#include "baset.h"

using MyType = BaseT<CustomClass1>;

template<>
class BaseT<CustomClass1> : public Interface
{
public:
BaseT() = default;

void pureMethod1() final {}
void pureMethod2() final {}
};

specialized2.h

#include "baset.h"

using MyType = BaseT<CustomClass2>;

template<>
class BaseT<CustomClass2> : public Interface
{
public:
BaseT() = default;

void pureMethod1() final {}
void pureMethod2() final {}
};

我在两个完全特化的类(class)中都收到了来自 clang 的警告:

警告:“BaseT 没有外联虚方法定义:它的 vtable 将在每个翻译单元中发出”

为什么这个警告?我没有任何纯虚析构函数,基类中提供了一个默认的析构函数。由于我使用的是模板,我该如何避免使用外线虚拟方法?

最佳答案

虚函数的解析通常是通过使用函数指针表,vtable来实现的。每个实现(即继承自)接口(interface)的类都有这样一个表,其中的条目指向它对虚函数的实现。该表必须位于编译期间生成的至少一个目标文件中,默认情况下,许多编译器将其放在包含类中第一个虚函数实现的目标文件中。

在您的情况下,BaseT 特化中的所有虚函数都在类声明中内联定义。在这种情况下,没有唯一的目标文件来放置它们的实现,它们将包含在使用它的所有目标文件中。这反过来意味着将 vtable 与第一个虚函数的实现放在一起的方法将不再有效。这使得编译器回退到所有目标文件中添加一个 vtable 版本,只是为了安全,并让程序员意识到这一点,它会发出警告。

这不是真正的问题,因为链接器将从目标文件之一中选择 vtable 并将其包含在最终二进制文件中。

关于c++ - 全特化模板类没有外线虚方法定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51263053/

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