Clang-Wweak vtables和纯抽象类
Clang -Wweak-vtables and pure abstract class
关于之前关于此主题的问题:
这是我最近问的问题的后续:clang:没有越界的虚拟方法定义(纯抽象C++类)其中被标记为这个问题的重复:clang的含义是什么;s-弱vtables?。我不认为这回答了我的问题,所以在这里,我专注于困扰我的事情,而这件事还没有得到回答。
我的场景:
我正在尝试使用Clang-3.5编译以下简单的C++代码:
test.h:
class A
{
public:
A();
virtual ~A() = 0;
};
test.cc
#include "test.h"
A::A() {;}
A::~A() {;}
我用来编译这个的命令(Linux,uname-r:3.16.0-4-amd64):
$clang-3.5 -Wweak-vtables -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]
当类A不是纯抽象的时,上面的代码构建得很好。以下代码不发出警告,唯一的变化是A类不再是抽象的:
test2.h:
class A
{
public:
A();
virtual ~A();
};
测试2.cc
#include "test2.h"
A::A() {;}
A::~A() {;}
我的问题
纯抽象类有什么特别之处,以至于上面的代码在Clang中触发警告?
具有虚拟方法的类总是需要发出vtable。编译器需要指示vtable存储在哪里——通常是在实现其第一个函数的对象中。
纯抽象类有什么特别之处?由于它们没有方法,编译器必须在每个翻译单元中输出一个vtable,这样每个翻译单元都可以引用纯抽象基类型。这就是警告告诉你的。
例如,如果你想避免在内存非常低的环境中复制内存,或者你在查看对象时想知道为什么这个地方有多个vtable副本,你可能会关心。
在任何情况下,您都可以使用指向A
对象的多态指针,这意味着编译器必须发出有关该类型的一些信息—vtable。
选项1:实现一个虚拟方法,例如析构函数
当创建一个抽象基类时,我的偏好是提供一个越界的虚拟析构函数;即在.cpp文件中实现A::~A()
。用户声明的虚拟析构函数的缺点是它隐式地删除了自动生成的复制和移动构造函数&运算符,因此最终需要重新声明它们。根据五条规则,这会产生这样的基类:
A.h:
class A {
public:
A() = default;
A(const A&) = default;
A(A&&) = default;
A& operator=(const A&) = default;
A& operator=(A&&) = default;
virtual ~A();
virtual void doSomething() = 0;
};
A.cpp:
A::~A()
{}
从技术上讲,它不再是一个纯粹的抽象基类,但它在功能上是相同的。您可以通过基指针进行安全销毁,它仍然允许对继承的类进行复制和移动构造,并且可以避免二进制文件中重复的vtables。
选项2:禁用警告
如果您愿意,您可以使用Clang的诊断杂注禁用该块的警告:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wweak-vtables"
class A {
public:
virtual void doSomething() = 0;
virtual ~A() = 0;
};
#pragma clang diagnostic pop
这就是你的困境:要么让类变得非纯粹抽象,要么关闭警告。根据您的要求,您可能更喜欢其中一个,但与所有警告一样,您应该仔细考虑。
- 无法创建抽象类的实例
- 用pybind11包装C++抽象类时出错
- 如何处理从一个对象传递到另一个在C++中具有公共抽象类的对象的消息
- 有没有办法按值将纯抽象类的所有子类传递给 C++ 中的函数?
- 抽象类错误,请参阅声明" "是抽象的
- 将自定义函数传递到基抽象类中以延迟执行
- 将包含抽象类和普通类C++包导出到 Python
- C++:处理抽象类中的错误时出现问题
- C ++如何在原始抽象类中创建一个函数,该函数接受派生类的输入
- 在 C++ 中使用另一个头文件中的抽象类
- ATL::CComContainedObject<contained>: C2259 无法实例化抽象类
- C++:从抽象类重写纯虚拟运算符重载
- 如何创建shared_ptr抽象类的容器
- .h 或.cpp文件中的抽象类或两者兼而有之?
- 从抽象类继承以创建另一个抽象类时,我应该重新声明所有虚函数吗?
- E0322:不允许使用抽象类类型 " " 的对象
- 可视抽象类 c++(错误 LNK 2001:未解析的外部符号)
- 了解虚拟继承类 vtables 和 vptr 创建
- 提升 - 类没有名为"序列化"的成员(抽象类)?
- Clang-Wweak vtables和纯抽象类