2012-06-04 26 views
3

我在一个普通的C(嵌入式项目,很少的内存)工作,我有一个结构如何继承结构在一个普通的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。

我知道这是可能的类型转换和偏移指针,我只是想知道是否有更好,更安全的方法。

+0

使用Kind1和Kind2的联合 – RolandXu

+1

http://stackoverflow.com/q/10872130/905902的可能重复,包括语法错误。 – wildplasser

+0

@wildplasser:我错过了这一个,很奇怪,我试着先搜索一下。 BTW,语法错误 - 你是什么意思?这显然是一种伪代码。 – Flot2011

回答

5

我知道这是可能的类型转换和偏移指针

不一定:

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

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

你可以做到这一点就像你在C将++:

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

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

struct Kind 
{ 
    Kind1 k1; 
    Kind2 k2; 
} 
+0

该项目专用于嵌入式设备,整个过程就是为了节省内存,否则我可以和Kind2一起生活。 – Flot2011

+0

删除了我的评论,有点太晚了。谢谢。 – BigMike

+0

@ Flot2011:听起来像是不成熟的优化,但您可以在任何给定的用例中使用Kind1,Kind2或Kind。 –

2

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

0

在内存有限的情况下,通过声明两个不同的结构保持理智:

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); 
    ... 
} 
0

我可以想到的一种方法,它将节省不超过2 * sizeof(float)个字节。

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

struct Kind1 
{ 
    int x; 
    int y; 
    float angle; 
    struct Kind2 *k2; 
} 

这里整个保存将基于指针吃掉多少内存。

只有在需要时才初始化指针。

2

下面的例子假定了这些定义。

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. 
}