通过类型双关的 C 继承,没有包含?

标签 c inheritance struct type-punning

我现在需要获得一些在 C 中工作的面向对象的特性,尤其是继承。幸运的是,有一些关于堆栈溢出的很好的引用资料,特别是这个 Semi-inheritance in C: How does this snippet work?还有这个Object-orientation in C .这个想法是在派生类中包含基类的实例并对其进行类型转换,如下所示:

struct base {
    int x;
    int y;
};

struct derived {
    struct base super;
    int z;
};

struct derived d;
d.super.x = 1;
d.super.y = 2;
d.z = 3;
struct base b = (struct base *)&d;

这很好,但是对于深度继承树来说它变得很麻烦 - 我将有大约 5-6 个“类”的链,我真的不想输入 derived.super.super.super.super.super.super每时每刻。我所希望的是我可以类型转换为前 n 个元素的结构,如下所示:

struct base {
    int x;
    int y;
};

struct derived {
    int x;
    int y;
    int z;
};

struct derived d;
d.x = 1;
d.y = 2;
d.z = 3;
struct base b = (struct base *)&d;

我已经在 Visual Studio 2012 附带的 C 编译器上对此进行了测试并且它可以工作,但我不知道 C 标准是否真的保证了它。有没有人可以确定这是否可以?我不想编写堆积如山的代码,却发现它在如此基础的层面上存在问题。

最佳答案

你在这里描述的是一个完全可移植的结构,并且基本上可以通过语言的设计保证工作,除了标准的作者认为没有必要明确要求编译器支持的东西这显然应该有效。 C89 为 union 指定了公共(public)初始序列规则,而不是指向结构的指针,因为给定:

struct s1 {int x; int y; ... other stuff... };
struct s2 {int x; int y; ... other stuff... };
union u { struct s1 v1; struct s2 v2; };

收到 struct s1* 的代码到一个外部物体 一个union u*或者 malloc 对象可以合法地将其转换为 union u* 如果它与该类型对齐,并且它可以合法地转换结果 指向 struct s2* 的指针,以及使用访问 struct s1* 的效果或 struct s2*必须与通过 v1 访问 union 相同或 v2成员。因此,编译器使所有指定规则起作用的唯一方法就是将一种结构类型的指针转​​换为另一种类型的指针,并使用该指针检查公共(public)初始序列的成员。

不幸的是,编译器作者说 CIS 规则仅适用于底层对象具有 union 类型的情况,尽管事实上这种情况代表了非常罕见的用例(与存在 union 类型的情况相比)让编译器知道为了检查 CIS 的目的,指向结构的指针应该互换处理的目的),并且进一步因为代码很少收到 struct s1*struct s2*标识 union u 中的对象,他们认为应该允许他们忽略这种可能性。因此,即使上面的声明可见,gcc 也会假定 struct s1*永远不会用于从 struct s2* 访问 CIS 的成员.

关于通过类型双关的 C 继承,没有包含?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18994551/

相关文章:

c - snprintf 不适用于 double。获取 '?'

c++ - 阻塞模式的原理是什么?

struct - 在Swift中以字符串的形式通过结构名称访问结构属性

c - 从进程 ID 获取窗口标题

c - 为什么堆栈看起来像这样?

javascript - 让变量继承现有原型(prototype)的方法?

css - 奇怪的从 "a"中的 "figure"元素继承到 "p"元素

从 void * 转换时的 C++ 多态性问题

c++ - 调用struct的虚函数时出现段错误

c - C 中以 NULL 结尾的结构类型数组