C中的结构继承

61 c structure

我可以在C中继承一个结构吗?如果有,怎么样?

Dan*_*ker 71

你能得到的最接近的是相当常见的习语:

typedef struct
{
    // base members

} Base;

typedef struct
{
    Base base;

    // derived members

} Derived;
Run Code Online (Sandbox Code Playgroud)

作为Derived与副本开始Base,你可以这样做:

Base *b = (Base *)d;
Run Code Online (Sandbox Code Playgroud)

在哪里d的实例Derived.所以他们有点多态.但是拥有虚拟方法是另一个挑战 - 要做到这一点,你需要拥有相当于vtable的指针Base,包含函数指针,这些函数可以接受Base作为第一个参数(你可以命名this)的函数.

到那时,你可以使用C++!

  • 那么,假设您的平台可以使用C++编译器! (5认同)
  • 如果C编译器可用,那么C++编译器也是如此 - 只需使用一个产生C作为其输出的编译器. (4认同)
  • 呼..你救了我的命。我通常用 Java 编写代码,当遇到与您发布的代码类似的代码时,我认为这是一个组合,并且在他们投射时感到非常困惑。 (2认同)
  • 您可以在复杂的实际项目(如 git)中看到它的用途。参见 [log-tree.c](https://github.com/git/git/blob/master/log-tree.c#L133)。[结构标签](https://github.com/git/git/blob/master/tag.h#L8) 从[结构对象](https://github.com/git/git/blob/)“继承”主/对象.h#L27) (2认同)

小智 42

与C++不同,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;
Run Code Online (Sandbox Code Playgroud)

  • C表示在结构的第一个成员之前没有填充.所以你实际上(并且被允许)可以将LiteraryCharacter*转换为Person*,并将其视为一个人.+1 (48认同)
  • @ JohannesSchaub-litb你的评论比答案本身更好的解释:) (4认同)
  • 需要注意的是,您必须只将这些类型传递给引用。您不能将它们复制到 Person 对象中,否则它会拼接。 (2认同)

Mar*_*tin 34

我喜欢并使用C中Typesafe继承的想法.

例如:

struct Animal
{
    int weight;
};

struct Felidae
{
    union {
      struct Animal animal;
    } base;
    int furLength;
};

struct Leopard
{
    union {
      struct Animal animal;
      struct Felidae felidae;
    } base;

    int dotCounter;
};
Run Code Online (Sandbox Code Playgroud)

用法:

struct Leopard leopard;
leopard.base.animal.weight = 44;
leopard.base.felidae.furLength = 2;
leopard.dotCounter = 99;
Run Code Online (Sandbox Code Playgroud)

  • @Alexander Torstling不,你不会.`leopard.base.felidae.base.animal.weight`只是`leopard.base.animal.weight`的另一个名字 - 它在内存中的同一个地方也是一样的. (3认同)
  • 有趣的方法。但是,一旦您输入“ leopard.base”,继承/多态性的整个点就被消除了。 (2认同)

Mat*_*att 9

如果你想使用一些gcc魔法(我认为可以使用微软的C编译器),你可以做类似的事情:


struct A
{
   int member1;
};

struct B
{
   struct A;
   int member2;
}
Run Code Online (Sandbox Code Playgroud)

使用gcc,您可以使用-fms-extensions编译它(允许未命名的struct成员,如Microsofts编译器).这类似于Daniel Earwicker给出的解决方案,除了它允许您访问struct B实例上的memeber1.即B.member1而不是BAmember1.

这可能不是最便携的方法,如果使用C++编译器将无法工作(不同的语言语义意味着它重新声明/定义struct A而不是实例化它).

但是,如果你住在gcc/C的土地上,那么它将会起作用并完全按照你的意愿行事.


小智 8

如果您的编译器支持匿名结构,您可以这样做:

typedef struct Base
{
    // base members
} Base_t;

typedef struct
{
   struct Base;  //anonymous struct

   // derived members

} Derived_t;
Run Code Online (Sandbox Code Playgroud)

这样,基础结构成员可以直接获得,这更好.

  • 这实际上不适用于标准C(甚至不是C11). (7认同)
  • 后缀`_t`在POSIX中保留.做任何你想做的事情,只是被告知如果为POSIX系统(例如Linux)编写代码或者最终想要将代码移植到POSIX系统,你可能会遇到冲突. (5认同)

Jar*_*Par -6

你不能。C不支持继承的概念。

  • 不支持,但也不妨碍。 (12认同)