이는 원하는 "개체 지향"기능 세트에 따라 다릅니다. 오버로드 및 / 또는 가상 메소드와 같은 것이 필요한 경우 구조에 함수 포인터를 포함해야합니다.
typedef struct {
float (*computeArea)(const ShapeClass *shape);
} ShapeClass;
float shape_computeArea(const ShapeClass *shape)
{
return shape->computeArea(shape);
}
이를 통해 기본 클래스를 "상속"하고 적절한 함수를 구현하여 클래스를 구현할 수 있습니다.
typedef struct {
ShapeClass shape;
float width, height;
} RectangleClass;
static float rectangle_computeArea(const ShapeClass *shape)
{
const RectangleClass *rect = (const RectangleClass *) shape;
return rect->width * rect->height;
}
물론 함수 포인터가 올바르게 설정되도록 생성자를 구현해야합니다. 일반적으로 인스턴스에 메모리를 동적으로 할당하지만 호출자에게도 그렇게 할 수 있습니다.
void rectangle_new(RectangleClass *rect)
{
rect->width = rect->height = 0.f;
rect->shape.computeArea = rectangle_computeArea;
}
여러 개의 다른 생성자를 원하면 함수 이름을 "장식"해야하며 둘 이상의 rectangle_new()
함수를 가질 수 없습니다 .
void rectangle_new_with_lengths(RectangleClass *rect, float width, float height)
{
rectangle_new(rect);
rect->width = width;
rect->height = height;
}
사용법을 보여주는 기본 예는 다음과 같습니다.
int main(void)
{
RectangleClass r1;
rectangle_new_with_lengths(&r1, 4.f, 5.f);
printf("rectangle r1's area is %f units square\n", shape_computeArea(&r1));
return 0;
}
나는 이것이 적어도 당신에게 아이디어를 줄 수 있기를 바랍니다. C에서 성공적이고 풍부한 객체 지향 프레임 워크를 보려면 glib의 GObject 라이브러리를 살펴보십시오 .
또한 위에서 모델링 한 명시적인 "클래스"가 없으며 각 객체에는 일반적으로 C ++에서 찾을 수있는 것보다 약간 더 유연한 고유 한 메서드 포인터가 있습니다. 또한 메모리 비용이 듭니다. class
구조체 에서 메서드 포인터를 채워서 각 개체 인스턴스가 클래스를 참조 할 수있는 방법을 만들어서 그로부터 벗어날 수 있습니다 .