Development Tip

C에서 OO 스타일 다형성을 어떻게 시뮬레이션 할 수 있습니까?

yourdevel 2020. 11. 3. 19:21
반응형

C에서 OO 스타일 다형성을 어떻게 시뮬레이션 할 수 있습니까?


C프로그래밍 언어로 OO와 유사한 코드를 작성하는 방법이 있습니까?


또한보십시오:

"[c] oo"를 검색하여 찾았습니다.


첫 번째 C ++ 컴파일러 ( "C with classes")는 실제로 C 코드를 생성하므로 확실히 가능합니다.

기본적으로 기본 클래스는 구조체입니다. 파생 된 구조체는 첫 번째 위치에 기본 구조체를 포함해야하므로 "파생 된"구조체에 대한 포인터도 기본 구조체에 대한 유효한 포인터가됩니다.

typedef struct {
   data member_x;
} base;

typedef struct {
   struct base;
   data member_y;
} derived;

void function_on_base(struct base * a); // here I can pass both pointers to derived and to base

void function_on_derived(struct derived * b); // here I must pass a pointer to the derived class

함수는 함수 포인터로서 구조체의 일부가 될 수 있으므로 p-> call (p)와 같은 구문이 가능해 지지만 여전히 함수 자체에 구조체에 대한 포인터를 명시 적으로 전달해야합니다.


일반적인 접근 방식은 함수에 대한 포인터로 구조체를 정의하는 것입니다. 이것은 모든 유형에서 호출 할 수있는 '메서드'를 정의합니다. 그런 다음 하위 유형은이 공통 구조에 자체 함수를 설정하고 반환합니다.

예를 들어 Linux 커널에는 struct가 있습니다.

struct inode_operations {
    int (*create) (struct inode *,struct dentry *,int, struct nameidata *);
    struct dentry * (*lookup) (struct inode *,struct dentry *, 
                               struct nameidata *);
    ...
};

파일 시스템의 각 유형은 등록에 대한 고유 기능 레지스터 create, lookup및 나머지 기능한다. 나머지 코드는 일반 inode_operations를 사용할 수 있습니다.

struct inode_operations   *i_op;
i_op -> create(...);

C ++는 C와 그리 멀지 않습니다.

클래스는 VTable이라는 함수 포인터 테이블에 대한 숨겨진 포인터가있는 구조입니다. Vtable 자체는 정적입니다. 형식이 동일한 구조를 가진 Vtables를 가리 키지 만 포인터가 다른 구현을 가리키는 경우 다형성이 발생합니다.

코드 혼란을 피하기 위해 구조체를 매개 변수로 사용하는 함수에서 호출 논리를 캡슐화하는 것이 좋습니다.

또한 구조체 인스턴스화 및 초기화를 함수 (C ++ 생성자와 동일) 및 삭제 (C ++의 소멸자)에 캡슐화해야합니다. 어쨌든 이것들은 좋은 습관입니다.

typedef struct
{
   int (*SomeFunction)(TheClass* this, int i);
   void (*OtherFunction)(TheClass* this, char* c);
} VTable;

typedef struct
{
   VTable* pVTable;
   int member;

} TheClass;

메서드를 호출하려면 :

int CallSomeFunction(TheClass* this, int i)
{
  (this->pVTable->SomeFunction)(this, i);
}

나는 다른 모든 사람들의 대답을보고 다음과 같이 생각해 냈습니다.

#include <stdio.h>

typedef struct
{
    int (*get)(void* this);
    void (*set)(void* this, int i);
    int member;

} TheClass;

int Get(void* this)
{
    TheClass* This = (TheClass*)this;
    return This->member;
}

void Set(void* this, int i)
{
    TheClass* This = (TheClass*)this;
    This->member = i;
}

void init(TheClass* this)
{
    this->get = &Get;
    this->set = &Set;
}

int main(int argc, char **argv)
{
    TheClass name;
    init(&name);
    (name.set)(&name, 10);
    printf("%d\n", (name.get)(&name));
    return 0;
}

몇 가지 질문에 대한 답이 되었기를 바랍니다.


Ian Piumarta와 VPRI의 Alessandro Warth가 작성한 Open Reusable Object Models 기사의 부록 B는 약 140 줄의 코드로 GNU C에서 Object 모델을 구현 한 것입니다. 매혹적인 읽기입니다!

다음은 C ( 문 표현식 )에 대한 GNU 확장을 사용하여 객체에 메시지를 보내는 캐시되지 않은 매크로 버전입니다 .

struct object;

typedef struct object *oop; 
typedef oop *(*method_t)(oop receiver, ...);

//...

#define send(RCV, MSG, ARGS...) ({ \ 
    oop r = (oop)(RCV); \ 
    method_t method = _bind(r, (MSG)); \ 
    method(r, ##ARGS); \ 
}) 

같은 문서에서 봐 가지고 object, vtable, vtable_delegatedsymbol구조체를하고 _bindvtable_lookup기능.

건배!


파일 함수 fopen, fclose, fread는 C에서 OO 코드의 예입니다. 클래스의 개인 데이터 대신 데이터를 캡슐화하는 데 사용되는 FILE 구조에서 작동하며 C 함수는 멤버 클래스 함수로 작동합니다. http://www.amazon.com/File-Structures-Object-Oriented-Approach-C/dp/0201874016


#include <stdio.h>

typedef struct {
    int  x;
    int z;
} base;

typedef struct {
    base;
    int y;
    int x;
} derived;

void function_on_base( base * a) // here I can pass both pointers to derived and to base
{
    printf("Class base [%d]\n",a->x);
    printf("Class base [%d]\n",a->z);
}
void function_on_derived( derived * b) // here I must pass a pointer to the derived class
{
    printf("Class derived [%d]\n",b->y);
    printf("Class derived [%d]\n",b->x);
}

int main()
{
    derived d;
    base b;
    printf("Teste de poliformismo\n");

    b.x = 2;
    d.y = 1;
    b.z = 3;
    d.x = 4;
    function_on_base(&b);
    function_on_base(&d);
    function_on_derived(&b);
    function_on_derived(&d);
    return 0;
}

출력은 다음과 같습니다.

Class base [3]
Class base [1]
Class base [4]
Class derived [2]
Class derived [3]
Class derived [1]
Class derived [4]

그래서 작동합니다. 다형성 코드입니다.

UncleZeiv는 처음에 그것에 대해 설명했습니다.


위키 백과에서 : 프로그래밍 언어와 유형 이론에서 다형성 (그리스어 πολύς, polys, "many, much"및 μορφή, morphē, "form, shape")은 서로 다른 유형의 엔티티에 대한 단일 인터페이스를 제공합니다.

So I would say the only way to implement it in C is by using variadic arguments along with some (semi)automatic type info management. For example in C++ you can write (sorry for trivialness):

void add( int& result, int a1, int a2 );
void add( float& result, float a1, float a2 );
void add( double& result, double a1, double a2 );

In C, among other solutions, the best you can do is something like this:

int int_add( int a1, int a2 );
float float_add( float a1, fload a2 );
double double_add( double a1, double a2 );

void add( int typeinfo, void* result, ... );

Then you need:

  1. to implement the "typeinfo" with enums/macros
  2. to implement the latter function with stdarg.h stuff
  3. to say goodbye to C static type checking

I am almost sure that any other implementation of polymorphism should look much like this very one. The above answers, instead, seems to try to address inheritance more than polymorphism!


In order too build OO functionality in C, you can look at previous answers.

But, (as it has been asked in other questions redirected to this one) if you want to understand what polymorphism is, by examples in C language. Maybe I am wrong, but I can't think of anything as easy to understand as C pointers arithmetic. In my opinion, pointer arithmetic is inherently polymorphic in C. In the following example the same function (method in OO), namely the addition (+), will produce a different behavior depending on the properties of the input structures.

Example:

double a*;
char str*;

a=(double*)malloc(2*sizeof(double));
str=(char*)malloc(2*sizeof(char)); 

a=a+2; // make the pointer a, point 2*8 bytes ahead.

str=str+2; // make the pointer str, point 2*1 bytes ahead.

Disclaimer: I am very new at C and very much looking forward to being corrected and learn from other user's comments, or even completely erase this answer, should it be wrong. Many thanks,

참고URL : https://stackoverflow.com/questions/524033/how-can-i-simulate-oo-style-polymorphism-in-c

반응형