c++规范是否允许非虚类的实例包含虚值表指针的内存?
Does the C++ spec allow an instance of a non-virtual class to include memory for a vtable pointer?
c++规范允许非虚类的实例包含虚表指针的内存吗?我之所以问这个问题,是因为一位同事说他曾经使用过一个c++编译器,其中发生了以下情况:
class MyClass
{
public:
HeaderStruct header; //This had extra words
BodyStruct message_body;
};
然后他把代码改成了这样,去掉了多余的单词:
struct MyClass
{
HeaderStruct header; //This did not have extra words
BodyStruct message_body;
};
这些类型都不是虚的或派生自虚的。所以理论是,也许这个特定的编译器为类实例分配内存,而不是为结构实例分配内存。所以我只是想确定这样的编译器行为是否被规范排除。
谢谢!
肯根据标准,'struct'和'class'是同义词,只影响对类定义中的基和成员的默认访问。
标准定义POD(普通旧数据)。POD不能有用户定义的构造函数、析构函数、赋值操作符、非静态引用成员和任何虚函数(它的非静态成员也不应该有这些东西)。pod有严格的内存布局规则(为了与C兼容),因此实现不能添加任何变量或RTTI信息或类似的东西。
然而,过去的c++编译器确实经常偏离标准,而且彼此之间也相差很大,所以你的同事可能也是对的。
我无法通过快速搜索找到在线参考,但我很确定编译器被允许对任何类的布局做任何事情;特别是,在没有任何虚拟方法的类中,允许放置vftp或不放置vftp,这取决于它当天的感觉,是否声明为class
或struct
(在c++中是等效的,除了默认的访问说明符),月相或其他任何东西。我所知道的唯一限制是派生对象的顶部必须匹配其第一个(非虚拟)基类的布局。我甚至不确定它一定是第一个。
在任何时候都不应该依赖于特定编译器对对象布局的决定。许多编译器将vftp毫无例外地放在所有对象中,以便向调试器提供运行时类型信息,或者只是为了使它们自己的工作更轻松。一些不喜欢。你没有合理的方法知道,除非通过sizeof
操作符。
没有"虚拟类"这回事。您可能指的是虚拟继承,它涉及在类名之前使用virtual
关键字,但是虚拟性适用于继承关系,而不是类本身。或者你只是指包含虚函数的类。
无论如何,c++规范根本没有提到虚表;这些是特定于实现的。通常,只有当类包含虚函数、具有虚基或继承了具有虚基的其他类时,才会添加虚表。但是,在every类的every实例中放置一个虚表是完全有效的实现。
类的虚修饰符仅在可能不止一次继承该类时使用。在I/O流库中,istream和ostream都继承自ios_base,而iostream继承自istream和ostream。虚修饰符允许您继承两次,而无需获得基类成员的两个副本。
但是任何方法都可以是虚的,即使在非虚类中也是如此——因此任何类都可以有虚函数表。
但是你的问题的真正答案:)是类和结构几乎是相同的,除了在类中,成员默认是私有的,而在结构中,他们默认是公共的。
- 为什么包含windows.h会产生语法错误,从而阻止类的实例化?(C2146,C2065)
- 使用用户定义的类型 UDT 实例化 std::atomic<>。如果 UDT 具有虚函数,则 l 墨水将失败。为什么?
- 使用包含互斥锁的类的方法实例化 cpp11 线程
- 如何使用包含内部类的类实例有效地从内部类访问成员?
- 如何为包含另一个类实例的数组制作常量 getter?
- 包含不同大小静态数组的类的多个实例
- VTBL 是否包含指向非虚函数的指针?
- 在C++中,为什么仅包含与其基类实例的联合的派生类占用的内存多于联合的大小?
- 无法编译包含"if constexpr"的函数模板实例化
- 通过派生类的实例在基中调用纯虚函数
- 如何操作包含"unique_ptr"的类的实例?
- 包含另一个实例的特征实例,该实例持有固定大小的特征对象
- 包含虚函数的类可以成为单例
- 如何在C++中仅包含一个实例创建类
- 包含自身实例化的模板,C++中的递归
- C++:包含类实例的并集调用了错误的虚拟函数
- 删除包含其他实例的实例的操作符
- 使用多态基类(包含虚函数)访问数组元素时的类型
- 模板包含虚函数是否安全?
- c++规范是否允许非虚类的实例包含虚值表指针的内存?