我可以继承 C 语言的结构吗? 如果可以,怎么继承?
不,你不能。 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;
当 Derived以 Base的副本开始时,您可以这样做:
Derived
Base
Base *b = (Base *)d;
其中 d是 Derived的实例。所以它们是多态的。但是使用虚方法是另一个挑战——要做到这一点,您需要使用相当于 Base中 vtable 指针的函数,包含接受 Base作为第一个参数的函数的函数指针(您可以将其命名为 this)。
d
this
在这一点上,您可以使用 C + + !
你可以做上面提到的
但是,如果希望避免指针强制转换,可以使用指向 Base和 Derived的 union的指针。
union
我喜欢并使用了 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