如何在普通C语言中继承结构

如何在普通C语言中继承结构,c,inheritance,data-structures,C,Inheritance,Data Structures,我在一个普通的C(嵌入式项目,很少的内存)中工作,我有一个结构 typedef struct { int x; int y; int z; float angle; float angle1; float angle2; } Kind1; 有时我需要所有字段,有时我只需要x、y和角度 C++中,我将创建一个具有这3个字段的基类,将从另一个类继承3个字段,并根据每个需求实例化一个或另一个。如何在普通C中模拟这种行为 我知道我可以做一些像 typedef s

我在一个普通的C(嵌入式项目,很少的内存)中工作,我有一个结构

typedef struct 
{
   int x;
   int y;
   int z;
   float angle;
   float angle1;
   float angle2;
} Kind1;
有时我需要所有字段,有时我只需要x、y和角度

C++中,我将创建一个具有这3个字段的基类,将从另一个类继承3个字段,并根据每个需求实例化一个或另一个。如何在普通C中模拟这种行为

我知道我可以做一些像

typedef struct 
{
   int x;
   int y;
   float angle;
} Kind1;

typedef struct
{ 
   Kind1 basedata;
   int z;
   float angle2;
   float angle3;
}  Kind2;
但我不能传递指向Kind2的指针,因为请求了指向Kind1的指针


我知道可以对指针进行类型转换和偏移,我只是想知道是否有更好、更安全的方法。

您可以像在C++中一样执行此操作:

struct Kind1
{
   int x;
   int y;
   float angle;
}

struct Kind2
{ 
   int z;
   float angle2;
   float angle3;
}

struct Kind
{
    Kind1 k1;
    Kind2 k2;
}
我知道可以对指针进行类型转换和偏移

不一定:

void foo(Kind1*);
struct Kind2
{ 
   Kind1 basedata;
   int z;
   float angle2;
   float angle3;
}

//...
Kind2 k;
foo(&(k.basedata));

这在普通C语言中是不可能的,这种语言没有这样的特性。但是,您可以使用预处理器宏简化类型转换和偏移量。

在内存有限的情况下,通过声明两个不同的结构来保持完整性:

struct Kind1
{
   int x;
   int y;
   float angle;
}

struct Kind2
{ 
   int x;
   int y;
   int z;
   float angle;
   float angle2;
   float angle3;
}
我曾经不得不编写代码,使用联合和预处理器
#define
s使代码看起来更可读。然而,这很快就会导致疯狂。如果这两个结构实际上是作为一个子类处理的,那么重新排列字段是最无害的:

struct Kind1
{
   int x;
   int y;
   float angle;
}

struct Kind2
{ 
   int x;
   int y;
   float angle;
   // extended data:
   int z;
   float angle2;
   float angle3;
}
只要它们与铸件一起小心使用。但是,如果出现任何错误,则应该进行调试版本名称检查,以证明所有操作都是正确的

struct Kind1
{
   char variant[6];  // initialized to "kind1" 
   int x;
   int y;
   float angle;
}

struct Kind2
{ 
   char variant[6];  // initialized to "kind2" 
   int x;
   int y;
   float angle;
   // extended data:
   int z;
   float angle2;
   float angle3;
}

function_expecting_kind2 (struct kind2 *p)
{
     if (strcmp (p->variant, "kind2"))
           error ("function expecting kind2 got '%s' instead", p->variant);
     ...
}

我能想到的一种方法将节省不超过2*sizeof(float)字节

在这里,整个节省将基于指针占用的内存量


仅在需要时初始化指针。

下面的示例采用这些定义

struct base { char c; } *a_base;
struct sub  { struct base b; int i; } *a_sub;

你的“例子”实际上是(最简单的)正确的解决方案

但我不能传递指向Kind2的指针,因为请求了指向Kind1的指针

是的,你可以。以下内容来自C11标准,但之前的修订版具有相同的保证[需要引用]

n1570 6.7.1.1.15 。。。经过适当转换的结构对象指针指向其初始成员(如果该成员是位字段,则指向其所在的单元),反之亦然。结构对象中可能有未命名的填充,但在其开头可能没有

因此
(struct base*)a_sub==&a_sub->b
((struct base*)a_sub)->c==a_sub->b.c

因此,只要您的“超级结构”是“子结构”的第一个成员,您就可以在通过引用访问时将一个视为另一个。基本上不要这样做

void copy(struct base *from, struct base *to)
{
    *to = *from; // Oops, you just lost half your object.
}

该项目是为嵌入式设备设计的,其目的是为了节省内存,否则我只能一直使用Kind2。删除我的评论,为时已晚。谢谢。@Flot2011:听起来像是过早的优化,但您可以根据任何给定的用例使用Kind1、Kind2或Kind。的可能重复,包括语法错误。@wildplasser:奇怪的是,我错过了这一个,我试着先搜索。顺便说一句,语法错误-你是什么意思?很明显,这是一种伪代码。它被标记为“C”,所以它不应该是伪代码。WRT语法错误:1)结构定义应以“;”结尾2) 结构标记{Kind1,Kind2}在C中不引入typedef(显然,在伪代码中它可以做任何事情)
void copy(struct base *from, struct base *to)
{
    *to = *from; // Oops, you just lost half your object.
}