Is it possible to inherit from an abstract / base structure or model something along these lines in C?

I am currently working with a C program that uses structures consisting of xyz coordinates, but sometimes these coordinates can refer to vectors (type Force / velocity, not a data structure), while in other cases this can relate to position. I know that you can just use one structure for all these different conditions, since they all use basically the same data type (float), but just keep my math better organized (plus the names of variables and structures) and not confuse things from confusion, is there a way to determine the basic structure, which defines itself as having three floats, is inherited by another structure, which more specifically determines what the structure should be (for example, position instead of speed, etc., etc.)? I know that C is not OOP, but it seems like it is possible.Here's what the basic structure will look like:

struct ThreeDCartesianData
{
   float x;
   float y;
   float z;
};

A more specific structure inherits from this and possibly defines additional variables or uses different names for variables. Several position structures will be used, but I think that for each data set there is only one velocity structure. I saw similar questions to this, but they all seem to refer to a higher level language (C ++, C #, etc.).

+4
source share
3 answers

You can use for this union. Your primary structwill contain union“derived” structures, as well as a flag field that tells you which member of the union is valid:

enum { DERIVED11, DERIVED2, DERIVED3 };

struct derived1 { int x1; };
struct derived2 { char x2; };
struct derived3 { float x3; };

struct ThreeDCartesianData
{
   float x;
   float y;
   float z;
   int derivedType;
   union {
     struct derived1 d1;
     struct derived2 d2;
     struct derived3 d3;
   } derived;
};

Then you can use them as follows:

struct ThreeDCartesianData data1;
data1.x=0;
data1.y=0;
data1.z=0;
data1.derivedType = DERIVED1;
data1.derived.d1.x1 = 4;

You can alternately define them as follows:

struct common
{
   int type;
   float x;
   float y;
   float z;
};
struct derived1
{
   int type;
   float x;
   float y;
   float z;
   int x1;
};
struct derived2
{
   int type;
   float x;
   float y;
   float z;
   char x2;
};
struct derived3
{
   int type;
   float x;
   float y;
   float z;
   float x3;
};

union ThreeDCartesianData {
     struct common c;
     struct derived1 d1;
     struct derived2 d2;
     struct derived3 d3;
};    

:

union ThreeDCartesianData data1;
data1.c.type=DERIVED1;
data1.d1.x=0;
data1.d1.y=0;
data1.d1.z=0;
data1.d1.x1 = 4;

, .

+3

typedef s?

typedef struct general3d {
    float x;
    float y;
    float z;
} general3d_t;

typedef general3d position;
typedef general3d velocity;

, - velocity, , 3 , x, y, z. , velocity, position. , general3d , general3d , position, velocity ; / .

EDIT: , .

, struct, , , , , struct s. :

struct point3d {
    float x;
    float y;
    float z;
};

struct person {
    float age;
    float weight;
    float salary;
};

, 3 , , , . , name person, char * point3d. , .

, struct, struct s:

struct point3d {
    float x;
    float y;
    float z;
};

struct person {
    point3d position;
    float age;
    float weight;
    float salary;
};

// access like:
person.position.x;
+3

I used to do this. I insert a copy of the base type at the beginning of the structure of the derived type. This more accurately mimics what it can do c++. Here are two methods that I used.


Using a simple type:

#define XYZDEF \
    int type; \
    float x; \
    float y; \
    float z

// base type
struct xyzdata {
    XYZDEF;
};

// derived type 1
struct vector {
    XYZDEF;
    int vector_info;
    ...
};

// derived type 2
struct position {
    XYZDEF;
    int position_info;
    ...
};

#define BASEOF(_ptr) \
    ((struct xyzdata *) (_ptr))

// vector_rotate -- rotate a vector
void
vector_rotate(vector *ptr)
{
}

// position_rotate -- rotate a position
void
position_rotate(position *ptr)
{
}

// xyzrotate -- rotate
void
xyzrotate(xyzdata *ptr)
{

    switch (ptr->type) {
    case TYPE_POSITION:
        vector_rotate((vector *) ptr);
        break;
    case TYPE_VECTOR:
        position_rotate((position *) ptr);
        break;
    }
}

Using the table pointer of a virtual function:

#define XYZDEF \
    int type; \
    vtbl *vtbl; \
    float x; \
    float y; \
    float z

// forward definitions
struct xyzdata;
struct vector;
struct position;

// virtual function table
struct vtbl {
    void (*rotate)(struct xyzdata *);
};

// base type
struct xyzdata {
    XYZDEF;
};

// derived type 1
struct vector {
    XYZDEF;
    int vector_info;
    ...
};

// derived type 2
struct position {
    XYZDEF;
    int position_info;
    ...
};

#define BASEOF(_ptr) \
    ((struct xyzdata *) (_ptr))

// vector_rotate -- rotate a vector
void
vector_rotate(struct xyzdata *ptr)
{
    struct vector *vec = (void *) ptr;
    ...
}

// position_rotate -- rotate a position
void
position_rotate(struct xyzdata *ptr)
{
    struct position *pos = (void *) ptr;
    ...
}

// xyzrotate -- rotate
void
xyzrotate(xyzdata *ptr)
{

    ptr->vtbl->rotate(ptr);
}
+1
source

Source: https://habr.com/ru/post/1624182/


All Articles