我知道多重继承的内存布局没有定义,所以我不应该依赖它。但是,在特殊情况下,我可以依赖它吗?也就是说,一个类只有一个“真正的”超级类。所有其他类都是“空类”,即既没有字段也没有虚拟方法的类(即它们只有非虚拟方法)。在这种情况下,这些附加类不应该在类的内存布局中添加任何内容(更简洁地说,在C 11的措辞中,该类具有标准布局)
我能推断出所有的超类都没有偏移吗?例如。:
#include <iostream>
class X{
int a;
int b;
};
class I{};
class J{};
class Y : public I, public X, public J{};
int main(){
Y* y = new Y();
X* x = y;
I* i = y;
J* j = y;
std::cout << sizeof(Y) << std::endl
<< y << std::endl
<< x << std::endl
<< i << std::endl
<< j << std::endl;
}
在这里,Y
是类,其中 X
是唯一真正的基类。程序的输出(在带有g 4.6的linux上编译时)如下:
8个。
0x233f010号
0x233f010号
0x233f010号
0x233f010号
正如我所总结的,没有指针调整。但是这个实现是特定的还是我可以依赖它。也就是说,如果我收到一个I
类型的对象(我知道只有这些类存在),我可以使用一个reinterpret_cast
将其转换为X
吗?
我希望我可以依赖它,因为规范规定对象的大小必须至少是一个字节。因此,编译器无法选择其他布局。如果它将I
和J
布局在
我是对的,还是我在这里使用从I
到X
reinterpret_cast,我是在玩火?
在C 11中,编译器需要对标准布局类型使用空基类优化。参见https://stackoverflow.com/a/10789707/981959
对于您的具体示例,所有类型都是标准布局类,没有通用的基类或成员(见下文),因此您可以依赖C 11中的行为(实际上,我认为许多编译器已经遵循了该规则,当然G也遵循了该规则,而其他编译器则遵循了Itanium C ABI。)
警告:确保你没有任何相同类型的基类,因为它们必须在不同的地址,例如
struct I {};
struct J : I {};
struct K : I { };
struct X { int i; };
struct Y : J, K, X { };
#include <iostream>
Y y;
int main()
{
std::cout << &y << ' ' << &y.i << ' ' << (X*)&y << ' ' << (I*)(J*)&y << ' ' << (I*)(K*)&y << '\n';
}
印刷品:
0x600d60 0x600d60 0x600d60 0x600d60 0x600d61
对于类型 Y
,只有一个 I
基可以处于偏移零,因此尽管 X
子对象处于偏移零(即 offsetof(Y, i)
为零)并且其中一个 I
基位于同一地址,但另一个 I
基是(至少用 G 和 Clang)进入对象的一个字节, 因此,如果您获得I *
,则无法reinterpret_cast
X*
,因为您不知道它指向哪个I
子对象,即偏移量为0的I
或偏移量为1的I
。
编译器可以将第二个I
子对象放在偏移量1处(即在int
内部),因为I
没有非静态数据成员,因此您实际上不能取消引用或访问该地址的任何内容,只能获得指向该地址对象的指针。如果您将非静态数据成员添加到I
,那么Y
将不再是标准布局,也不必使用EBO,并且offsetof(Y, i)
将不再为零。
主要内容:多继承下的构造函数,命名冲突在前面的例子中,派生类都只有一个基类,称为 单继承(Single Inheritance)。除此之外, C++也支持 多继承(Multiple Inheritance),即一个派生类可以有两个或多个基类。 多继承容易让代码逻辑复杂、思路混乱,一直备受争议,中小型项目中较少使用,后来的 Java、 C#、 PHP 等干脆取消了多继承。 多继承的语法也很简单,将多个基类用逗号隔开即可。例如已声明了类A
在面向对象的程序设计中,定义一个新的 class 的时候,可以从某个现有的 class 继承,新的 class 称为子类,而被继承的 class 称为基类、父类或超类。 Python 中继承的语法如下: class Parent: pass class Child(Parent): pass 在第 1 行,定义了父类 Parent; 在第 4 行,定义了子类 Child,语法
本文向大家介绍关于C++对象继承中的内存布局示例详解,包括了关于C++对象继承中的内存布局示例详解的使用技巧和注意事项,需要的朋友参考一下 前言 本文给大家介绍的是关于C++对象继承的内存布局的相关内容,分享出来供大家参考学习,在开始之前说明下,关于单继承和多继承的简单概念可参考此文章 以下编译环境均为:WIN32+VS2015 虚函数表 对C++ 了解的人都应该知道虚函数(Virtual Fun
我有一个类,用于使用struct解码二进制数据并存储在NamedTuple中,如下所示: 这是没有问题的,我可以如下使用: 但是,如果我尝试将其更改为继承类方法,如下所示,它会失败: 然后它错误与。 我知道从NamedTuple继承有些问题,但我想知道是否有解决办法? 编辑:正如下面的其他人所暗示的那样,看起来数据类是要走的路:一种用于类型检查目的的子类命名Tuple的方法
本文向大家介绍C/C++ 公有继承、保护继承和私有继承的对比详解,包括了C/C++ 公有继承、保护继承和私有继承的对比详解的使用技巧和注意事项,需要的朋友参考一下 C/C++ 公有继承、保护继承和私有继承的区别 在c++的继承控制中,有三种不同的控制权限,分别是public、protected和private。定义派生类时,若不显示加上这三个关键字,就会使用默认的方式,用struct定义的类
问题内容: 我正在开发一个使用angular作为客户端框架的应用程序,目前使用angular作为岩石,我真的很高兴,尽管现在我发现我经常复制和粘贴要组织成类层次结构的代码。例如,对话框共享一组通用的功能,需要打开,关闭它们,提供功能的代码也是从某些父BaseTypeaheadClass继承的首选对象,尽管我在angular中没有发现的一件事是组织这些层次结构。控制器,服务和提供者都在下面使用普通的