在纯C中继承这样的继承
typedef struct {
char name[NAMESIZE];
char sex;
} Person;
typedef struct {
Person person;
char job[JOBSIZE];
} Employee;
typedef struct {
Person person;
char booktitle[TITLESIZE];
} LiteraryCharacter;
我知道可以将“LiteraryCharacter”类型的实例转换为“Person”类型,并将其用作此类。但是,将“LiteraryCharacter”类型的实例转换为“Employee”类型并使用它也是可以/安全吗?
答案 0 :(得分:1)
这样的强制转换在标准C中是未定义的行为,尽管它可以与许多编译器一起使用。
即使它适用于您当前使用的编译器,也要注意它可能会在未来版本的编译器中或使用不同的编译器中断。 C标准允许编译器假设指向不同类型的指针不指向相同的内存 - 除了一些记录良好的异常,包括LiteraryCharacter *
到Person *
的强制转换。将LiteraryCharacter *
强制转换为Employee *
的代码可以并且将在使用此假设生成有效代码的编译器下中断。
最好先解释为什么你认为你需要这个演员。它的等价在C ++中是非常不正确的,并在Java中生成ClassCastException
。毕竟,LiteraryCharacter
没有Person
的字段,例如job
。
答案 1 :(得分:0)
那将是未定义的行为。在C中没有继承这样的东西。
如果结构完全相同的布局,那么可能会侥幸逃脱它,但这确实是非常脆弱的代码。
答案 2 :(得分:0)
在您的示例中,您将转换为来自不兼容的类型,由于这两种类型的大小不同,因此甚至无法编译。但是,您可以转换为兼容(或甚至不兼容)的指针类型,它将进行编译。
从不兼容(或者说是伪兼容)类型转换为未定义的行为,在某些结构和编译器实现上,它将对其他人不会起作用。
只要编译器正在处理对象结构/内部对齐/内存布局等,转换为兼容 - 指针类型是安全的。(那里&# 39;以下是一个例子。)
" OK"部分是值得商榷的。它会起作用吗?是的,因为他们在记忆中有相同的""布局,你知道这个特定的事实。但是,当另一个程序员创建该结构时会发生什么?您必须阅读其来源以评估是否可以安全地转换为其他类型。
此外,大多数封装技术只会暴露一种" opaque类型"你可以通过指针使用它 - 将它传递给在同一个库/包中实现的函数,并且它们完成所有结构特定的工作。对于"不透明类型"你只知道那个结构存在,你不知道它的内部结构,所以你不能只改变你用来访问它的指针类型,因为你不能确保它背后的结构兼容性。
封装的目的是允许单独开发模块。因此,当这个外部模块的原始开发人员在将来的版本中更改结构时,它会破坏与代码的兼容性(无论如何都不应该以这种方式使用它)。
这是GCC的非标准(但几乎无处不在)编译器功能。
typedef struct {
char name[NAMESIZE];
char sex;
} Person;
typedef struct {
Person;
char job[JOBSIZE];
} Employee;
typedef struct {
Employee;
char booktitle[TITLESIZE];
} LiteraryEmployeeCharacter;
LiteraryEmployeeCharacter* lec = malloc(sizeof(LiteraryEmployeeCharacter));
lec->name = "My character";
lec->sex = 'F';
lec->job = "Steward";
lec->booktitle = "A book";
通过使用未命名的字段,您可以访问name
,sex
和job
,就好像它们已在LiteraryEmployeeCharacter
结构中定义一样。
通过强制转换为兼容的指针类型,编译器知道每个字段的确切结构和位置,并且可以轻松地正确处理结构。