C의 구조 상속
C에서 구조를 상속받을 수 있습니까? 그렇다면 어떻게?
가장 가까운 것은 매우 일반적인 관용구입니다.
typedef struct
{
// base members
} Base;
typedef struct
{
Base base;
// derived members
} Derived;
Derived
의 복사본으로 시작하면 다음과 같이 Base
할 수 있습니다.
Base *b = (Base *)d;
d
의 인스턴스는 어디에 있습니까 Derived
? 그래서 그들은 일종의 다형성입니다. 그러나 가상 메서드를 갖는 것은 또 다른 도전입니다. 그렇게하려면 첫 번째 인수로 Base
허용하는 함수에 대한 함수 포인터를 포함하는 에서 vtable 포인터에 해당하는 것이 있어야합니다 Base
(이름을 지정할 수 있음 this
).
어느 시점에서 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에서 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;
};
용법:
struct Leopard leopard;
leopard.base.animal.weight = 44;
leopard.base.felidae.furLength = 2;
leopard.dotCounter = 99;
gcc 마법을 사용하고 싶다면 (Microsoft의 C 컴파일러에서 작동한다고 가정합니다) 다음과 같이 할 수 있습니다.
struct A
{
int member1;
};
struct B
{
struct A;
int member2;
}
gcc를 사용하면 -fms-extensions로 컴파일 할 수 있습니다 (Microsoft 컴파일러처럼 이름이 지정되지 않은 구조체 멤버 허용). 이것은 struct B 인스턴스에서 memeber1에 액세스 할 수 있다는 점을 제외하면 Daniel Earwicker가 제공 한 솔루션과 유사합니다. 즉, BAmember1 대신 B.member1.
이것은 아마도 가장 이식 가능한 접근 방식이 아니며 C ++ 컴파일러를 사용하는 경우 작동하지 않을 것입니다 (다른 언어 의미론은 인스턴스화하는 대신 구조체 A를 다시 선언 / 정의한다는 것을 의미합니다).
그러나 gcc / C 토지에 거주하는 경우에만 작동하고 원하는대로 정확하게 수행 할 수 있습니다.
컴파일러가 익명 구조체를 지원하는 경우 다음을 수행 할 수 있습니다.
typedef struct Base
{
// base members
} Base_t;
typedef struct
{
struct Base; //anonymous struct
// derived members
} Derived_t;
이런 식으로 기본 stuct 멤버를 직접 액세스 할 수 있습니다.
위에서 언급 한 것을 할 수 있습니다.
typedef struct
{
// base members
} Base;
typedef struct
{
Base base;
// derived members
} Derived;
그러나 포인터 캐스팅을 피하려면 union
of Base
및에 대한 포인터를 사용할 수 있습니다 Derived
.
이것은 -fms-extensions로 컴파일됩니다.
main.c
#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
Book.c
#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;
}
Book.h
#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
Product.c
#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;
}
Product.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
Makefile
.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
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 = "...";
...
};
vs
# as in anon's answer
Employee e = {
.person.name = "...";
...
};
나는 이것이 몇몇 유명한 프로젝트가 그렇게하는 방법이라고 믿는다 (예 : libuv)
업데이트 : 또한 구조체와 공용체를 사용하는 libsdl 이벤트 구현에서 유사한 (동일하지는 않음) 개념의 좋은 예가 있습니다.
C is not an object-oriented language and hence has no inheritance.
You can simulate it, but you can't really inherit.
No, you cant. imo the best approach to OOP in C is using ADT.
No you cannot. C does not support the concept of inheritance.
참고URL : https://stackoverflow.com/questions/1114349/struct-inheritance-in-c
'Development Tip' 카테고리의 다른 글
redux-saga의 getState? (0) | 2020.11.29 |
---|---|
Visual Studio가 특정 DLL에 대한 기호를로드하지 못하도록 방지 (0) | 2020.11.29 |
System.Collections.Generic.List에 'Select'에 대한 정의가 없습니다. (0) | 2020.11.29 |
Angular 2 2.0.0-rc.1 속성 'map'이 'Observable 유형에 존재하지 않습니다. (0) | 2020.11.29 |
JSON을 사용하여 XmlHttpRequest POST 만들기 (0) | 2020.11.29 |