Struct Inheritance in C

后端 未结 12 1609
悲&欢浪女
悲&欢浪女 2020-11-29 00:04

Can I inherit a structure in C? If yes, how?

相关标签:
12条回答
  • 2020-11-29 00:34

    C is not an object-oriented language and hence has no inheritance.

    0 讨论(0)
  • 2020-11-29 00:39

    The closest you can get is the fairly common idiom:

    typedef struct
    {
        // base members
    
    } Base;
    
    typedef struct
    {
        Base base;
    
        // derived members
    
    } Derived;
    

    As Derived starts with a copy of Base, you can do this:

    Base *b = (Base *)d;
    

    Where d is an instance of Derived. So they are kind of polymorphic. But having virtual methods is another challenge - to do that, you'd need to have the equivalent of a vtable pointer in Base, containing function pointers to functions that accept Base as their first argument (which you could name this).

    By which point, you may as well use C++!

    0 讨论(0)
  • 2020-11-29 00:40

    If you want to use some gcc magic (that I would assume would work with Microsoft's C compiler) you can do something like:

    
    struct A
    {
       int member1;
    };
    
    struct B
    {
       struct A;
       int member2;
    }
    

    With gcc you can compile this with -fms-extensions (Allows for unnamed struct members like Microsofts compiler does). This is similar to the solution given by Daniel Earwicker except that it allows you to access memeber1 on a struct B instance. i.e B.member1 instead of B.A.member1.

    This is probably not the most portable approach and will not work if using a C++ compiler (different language semantics mean that it is redeclaring/defining struct A instead of instantiating it).

    If however you live in the gcc/C land only it will work and do exactly what you want.

    0 讨论(0)
  • 2020-11-29 00:40

    No, you cant. imo the best approach to OOP in C is using ADT.

    0 讨论(0)
  • 2020-11-29 00:42

    This works compiling with -fms-extensions

    Diagram image

    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
    
    0 讨论(0)
  • 2020-11-29 00:49

    I like and used the idea of Typesafe inheritance in C.

    For example:

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

    Usage:

    struct Leopard leopard;
    leopard.base.animal.weight = 44;
    leopard.base.felidae.furLength = 2;
    leopard.dotCounter = 99;
    
    0 讨论(0)
提交回复
热议问题