C 中的结构继承

我可以继承 C 语言的结构吗? 如果可以,怎么继承?

59953 次浏览

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

C 不是面向对象的语言,因此没有继承性。

你可以模拟它,但你不能 真的继承。

与 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;

不,你不能。 我认为 C 语言中面向对象的最佳方法是使用 ADT

你能得到的最接近的是一个相当常见的成语:

typedef struct
{
// base members


} Base;


typedef struct
{
Base base;


// derived members


} Derived;

DerivedBase的副本开始时,您可以这样做:

Base *b = (Base *)d;

其中 dDerived的实例。所以它们是多态的。但是使用虚方法是另一个挑战——要做到这一点,您需要使用相当于 Base中 vtable 指针的函数,包含接受 Base作为第一个参数的函数的函数指针(您可以将其命名为 this)。

在这一点上,您可以使用 C + + !

你可以做上面提到的

typedef struct
{
// base members


} Base;


typedef struct
{
Base base;


// derived members


} Derived;

但是,如果希望避免指针强制转换,可以使用指向 BaseDerivedunion的指针。

我喜欢并使用了 C 中的类型安全继承的概念。

例如:

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

用法:

struct Leopard leopard;
leopard.base.animal.weight = 44;
leopard.base.felidae.furLength = 2;
leopard.dotCounter = 99;

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

typedef struct Base
{
// base members
} Base_t;


typedef struct
{
struct Base;  //anonymous struct


// derived members


} Derived_t;

通过这种方式,可以直接访问基础结构成员,这样更好。

如果你想使用一些 gcc 的魔法(我假设它可以与微软的 C 编译器一起工作) ,你可以这样做:


struct A
{
int member1;
};


struct B
{
struct A;
int member2;
}

使用 gcc,您可以使用-fms-extons 编译它(允许像 Microsoft 编译器那样使用未命名的 struct 成员)。这与 Daniel Earwicker 提供的解决方案类似,只是它允许您在 structB 实例上访问 memeber1。即 B 成员1而不是 B 成员1。

这可能不是最可移植的方法,如果使用 C + + 编译器(不同的语言语义意味着它重新声明/定义结构 A 而不是实例化它) ,这种方法也不会起作用。

如果你只是生活在 gcc/c 的土地上,那么它将会工作并且做你想做的事情。

与 anon (和其他类似的)的答案稍有不同。对于一个层次的深度遗传,人们可以做到以下几点:

#define BASEFIELDS              \
char name[NAMESIZE];        \
char sex


typedef struct {
BASEFIELDS;
} Person;


typedef struct {
BASEFIELDS;
char job[JOBSIZE];
} Employee;


typedef struct {
BASEFIELDS;
Employee *subordinate;
} Manager;

这样,接受指向 Person 的指针的函数将接受指向 Employee 或 Manager 的指针(通过强制转换) ,与其他答案相同,但在这种情况下,初始化也是自然的:

Employee e = {
.name = "...";
...
};

# as in anon's answer
Employee e = {
.person.name = "...";
...
};

我相信一些流行的项目就是这样做的(例如 libuv)

更新: 在使用结构和联合的 libsdl 事件实现中,也有一些类似(但不相同)概念的好例子。

这可以使用-fms-扩展进行编译

图形图像

总机

#include "AbstractProduct.h"
#include "Book.h"
#include "Product.h"
#include "TravelGuide.h"


/***********************/


int main() {


Product p = Product_new();
p.set_id(&p, 2);
p.set_name(&p, "name2");
p.set_description(&p, "description2");
p.set_price(&p, 2000);
p.display(&p);


TravelGuide tg = TravelGuide_new();
tg.set_id(&tg, 1);
tg.set_name(&tg, "name1");
tg.set_description(&tg, "description1");
tg.set_price(&tg, 1000);
tg.set_isbn(&tg, "isbn1");
tg.set_author(&tg, "author1");
tg.set_title(&tg, "title1");
tg.set_country(&tg, "country1");
tg.display(&tg);


}

AbstractProduct.c

#include "AbstractProduct.h"


/*-------------------------------*/


static void set_id(AbstractProduct *this, int id) {
this->id = id;
}


/*-------------------------------*/


static void set_name(AbstractProduct *this, char *name) {
strcpy(this->name, name);
}


/*-------------------------------*/


static void set_description(AbstractProduct *this, char *description) {
strcpy(this->description, description);
}


/*-------------------------------*/


static int get_id(AbstractProduct *this) {
return this->id;
}


/*-------------------------------*/


static char *get_name(AbstractProduct *this) {
return this->name;
}


/*-------------------------------*/


static char *get_description(AbstractProduct *this) {
return this->description;
}


/*-------------------------------*/


static void display(AbstractProduct *this) {


printf("-AbstractProduct- \n");
printf("id: %d\n", this->get_id(this));
printf("name: %s\n", this->get_name(this));
printf("description: %s\n", this->get_description(this));
printf("\n");
}


/*-------------------------------*/


void AbstractProduct_init(AbstractProduct *obj) {


obj->set_id = set_id;
obj->set_name = set_name;
obj->set_description = set_description;
obj->get_id = get_id;
obj->get_name = get_name;
obj->get_description = get_description;
obj->display = display;


}


/*-------------------------------*/


AbstractProduct AbstractProduct_new() {


AbstractProduct aux;
AbstractProduct_init(&aux);
return aux;
}

AbstractProduct.h

#ifndef AbstractProduct_H
#define AbstractProduct_H


#include <stdlib.h>
#include <stdio.h>
#include <string.h>


/***********************/


typedef struct AbstractProduct{


int id;
char name[1000];
char description[1000];


void (*set_id)();
void (*set_name)();
void (*set_description)();
int (*get_id)();
char *(*get_name)();
char *(*get_description)();
void (*display)();


} AbstractProduct;


AbstractProduct AbstractProduct_new();
void AbstractProduct_init(AbstractProduct *obj);


#endif

#include "Book.h"


/*-------------------------------*/


static void set_isbn(Book *this, char *isbn) {
strcpy(this->isbn, isbn);
}


/*-------------------------------*/


static void set_author(Book *this, char *author) {
strcpy(this->author, author);
}


/*-------------------------------*/


static void set_title(Book *this, char *title) {
strcpy(this->title, title);
}


/*-------------------------------*/


static char *get_isbn(Book *this) {
return this->isbn;
}


/*-------------------------------*/


static char *get_author(Book *this) {
return this->author;
}


/*-------------------------------*/


static char *get_title(Book *this) {
return this->title;
}


/*-------------------------------*/


static void display(Book *this) {


Product p = Product_new();
p.display(this);


printf("-Book- \n");
printf("isbn: %s\n", this->get_isbn(this));
printf("author: %s\n", this->get_author(this));
printf("title: %s\n", this->get_title(this));
printf("\n");
}


/*-------------------------------*/


void Book_init(Book *obj) {


Product_init((Product*)obj);


obj->set_isbn = set_isbn;
obj->set_author = set_author;
obj->set_title = set_title;
obj->get_isbn = get_isbn;
obj->get_author = get_author;
obj->get_title = get_title;
obj->display = display;
}
/*-------------------------------*/


Book Book_new() {


Book aux;
Book_init(&aux);
return aux;
}

#ifndef Book_H
#define Book_H


#include <stdlib.h>
#include <stdio.h>
#include <string.h>


#include "Product.h"


/***********************/


typedef struct Book{


Product;
char isbn[1000];
char author[1000];
char title[1000];


void (*set_isbn)();
void (*set_author)();
void (*set_title)();


char *(*get_isbn)();
char *(*get_author)();
char *(*get_title)();
// void (*display)();




} Book;


Book Book_new();
void Book_init(Book *obj);


#endif

产品

#include "Product.h"


/*-------------------------------*/


static void set_price(Product *this, double price) {
this->price = price;
}


/*-------------------------------*/


static double get_price(Product *this) {
return this->price;
}


/*-------------------------------*/


static void display(Product *this) {


AbstractProduct p = AbstractProduct_new();
p.display(this);


printf("-Product- \n");
printf("price: %f\n", this->get_price(this));
printf("\n");
}


/*-------------------------------*/


void Product_init(Product *obj) {


AbstractProduct_init((AbstractProduct*)obj);


obj->set_price = set_price;
obj->get_price = get_price;
obj->display = display;


}


/*-------------------------------*/


Product Product_new() {


Product aux;
Product_init(&aux);
return aux;
}

产品.h

#ifndef Product_H
#define Product_H


#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "AbstractProduct.h"


/***********************/


typedef struct Product{


AbstractProduct;
double price;


void (*set_price)();
double (*get_price)();
// void (*display)();


} Product;


Product Product_new();
void Product_init(Product *obj);


#endif

TravelGuide.c

#include "TravelGuide.h"


/*-------------------------------*/


static void set_country(TravelGuide *this, char *country) {
strcpy(this->country, country);
}


/*-------------------------------*/


static char *get_country(TravelGuide *this) {
return this->country;
}


/*-------------------------------*/


static void display(TravelGuide *this) {


Book b = Book_new();
b.display(this);


printf("-TravelGuide- \n");
printf("country: %s\n", this->get_country(this));
printf("\n");
}


/*-------------------------------*/


void TravelGuide_init(TravelGuide *obj) {


Book_init((Book*)obj);
obj->set_country = set_country;
obj->get_country = get_country;
obj->f = obj->display;
obj->display = display;


}


/*-------------------------------*/


TravelGuide TravelGuide_new() {


TravelGuide aux;
TravelGuide_init(&aux);
return aux;
}

TravelGuide.h

#ifndef TravelGuide_H
#define TravelGuide_H


#include <stdlib.h>
#include <stdio.h>
#include <string.h>


#include "Book.h"


/***********************/


typedef struct TravelGuide{


Book;
char country[1000];
void (*f)();


void (*set_country)();
char *(*get_country)();
// void *(*display)();


} TravelGuide;


TravelGuide TravelGuide_new();
void TravelGuide_init(TravelGuide *obj);


#endif

马克菲尔

.PHONY: clean
define ANNOUNCE_BODY


***********************************************
************          start make **************
***********************************************
endef


all:
$(info $(ANNOUNCE_BODY))


clear;
if [ -f binary/main ]; then rm binary/main; fi;


# compiler


gcc $(INC) -c -fms-extensions main.c -o binary/main.o
gcc $(INC) -c -fms-extensions AbstractProduct.c -o binary/AbstractProduct.o
gcc $(INC) -c -fms-extensions Product.c -o binary/Product.o
gcc $(INC) -c -fms-extensions Book.c -o binary/Book.o
gcc $(INC) -c -fms-extensions TravelGuide.c -o binary/TravelGuide.o


# linker


gcc binary/main.o \
binary/AbstractProduct.o \
binary/Product.o \
binary/Book.o \
binary/TravelGuide.o \
-o \
binary/main