如果只是这样实现,那么无法多态。即给父类赋值子类,然后调用父类,实测还是调用的父类接口。因此添加虚函数表

This commit is contained in:
建峰 2024-09-01 03:22:37 +08:00
parent 196c331520
commit 7021105e64
3 changed files with 90 additions and 26 deletions

View File

@ -50,10 +50,10 @@ install(TARGETS demo DESTINATION bin)
install (FILES "${PROJECT_BINARY_DIR}/config.h" install (FILES "${PROJECT_BINARY_DIR}/config.h"
DESTINATION include) DESTINATION include)
# 4. 启用测试 # # 4. 启用测试
enable_testing() # enable_testing()
# 测试程序是否成功运行 # # 测试程序是否成功运行
add_test (NAME test_demo COMMAND demo 1 2 3 5 8) # add_test (NAME test_demo COMMAND demo 1 2 3 5 8)
# 5. 支持GDB # 5. 支持GDB
set(CMAKE_BUILD_TYPE "Debug") set(CMAKE_BUILD_TYPE "Debug")

102
main.c
View File

@ -3,28 +3,66 @@
#include <stdio.h> #include <stdio.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdlib.h> #include <stdlib.h>
#include <assert.h>
#define VIRTUAL #define VIRTUAL
#define PRIVATE
struct _virtual_table
{
VIRTUAL void (*area)(void *self);
VIRTUAL void (*draw)(void *self);
};
void virtual_area(void *self)
{
assert(!"can't call abstract method");
}
void virtual_draw(void *self)
{
assert(!"can't call abstract method");
}
struct _virtual_table *virtual_new(void)
{
struct _virtual_table *v = calloc(1, sizeof(struct _virtual_table));
if (v == NULL)
{
return NULL;
}
v->area = virtual_area;
v->draw = virtual_draw;
return v;
}
struct _shape struct _shape
{ {
VIRTUAL void (*area)(struct _shape *self); VIRTUAL void (*area)(void *self);
VIRTUAL void (*draw)(struct _shape *self); VIRTUAL void (*draw)(void *self);
}; };
void shape_area(struct _shape *self) void shape_area(void *self)
{ {
printf("shape area\n"); assert(!"can't call abstract method");
} }
void shape_draw(struct _shape *self) void shape_draw(void *self)
{ {
printf("shape draw\n"); assert(!"can't call abstract method");
} }
struct _shape *shape_new(void) struct _shape *shape_new(void)
{ {
struct _shape *shape = calloc(1, sizeof(struct _shape)); struct _shape *shape = calloc(1, sizeof(struct _shape));
if(shape == NULL)
{
return NULL;
}
shape->area = shape_area;
shape->draw = shape_draw;
return shape; return shape;
} }
@ -38,17 +76,19 @@ void shape_free(struct _shape * self)
} }
#endif #endif
#define SUPER(self) ((self)->shape)
struct _rect struct _rect
{ {
// super // super
// struct _shape shape; struct _shape* shape;
// attribute // attribute
double width, height; double width, height;
// method // method
void (*area)(struct _rect *self); // void (*area)(void *self);
void (*draw)(struct _rect *self); // void (*draw)(void *self);
}; };
void rect_area(struct _rect *self) void rect_area(struct _rect *self)
@ -71,22 +111,28 @@ struct _rect *rect_new(double width, double height)
rect->width = width; rect->width = width;
rect->height = height; rect->height = height;
rect->area = rect_area; rect->shape = shape_new();
rect->draw = rect_draw; if (rect->shape == NULL)
{
return NULL;
}
SUPER(rect)->area = (void (*)(void *self))rect_area;
SUPER(rect)->draw = (void (*)(void *self))rect_draw;
return rect; return rect;
} }
struct _circle struct _circle
{ {
// super // super
// struct _shape shape; struct _shape *shape;
// attribute // attribute
double radius; double radius;
// method // method
void (*area)(struct _circle *self); // void (*area)(void *self);
void (*draw)(struct _circle *self); // void (*draw)(void *self);
}; };
void circle_area(struct _circle *self) void circle_area(struct _circle *self)
@ -105,22 +151,38 @@ struct _circle *circle_new(double radius)
{ {
return NULL; return NULL;
} }
circle->shape = shape_new();
if (circle->shape == NULL)
{
return NULL;
}
circle->radius = radius; circle->radius = radius;
circle->area = circle_area; SUPER(circle)->area = (void (*)(void *self))circle_area;
circle->draw = circle_draw; SUPER(circle)->draw = (void (*)(void *self))circle_draw;
return circle; return circle;
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
struct _rect *rect = rect_new(4, 5); struct _rect *rect = rect_new(4, 5);
rect->area(rect); rect_area(rect);
rect->draw(rect); rect_draw(rect);
struct _circle *circle = circle_new(3); struct _circle *circle = circle_new(3);
circle->area(circle); circle_area(circle);
circle->draw(circle); circle_draw(circle);
// struct shape *shape = shape_new();
// shape_area(shape);
// shape_draw(shape);
// struct _shape *shape = NULL;
struct _shape *shape = rect_new(2,3);
// shape = rect;
shape_area(shape);
shape_draw(shape);
return 0; return 0;
} }

4
mk.bat
View File

@ -1,6 +1,8 @@
@REM D:\Lang\cmake-3.27.5-windows-x86_64\bin\cmake.EXE --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE -DCMAKE_C_COMPILER:FILEPATH=D:\Software\mingw64\bin\gcc.exe -DCMAKE_CXX_COMPILER:FILEPATH=D:\Software\mingw64\bin\g++.exe -SF:/OpenDemo/1_vsc_cmake -Bf:/OpenDemo/1_vsc_cmake/build -G "MinGW Makefiles" @REM D:\Lang\cmake-3.27.5-windows-x86_64\bin\cmake.EXE --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE -DCMAKE_C_COMPILER:FILEPATH=D:\Software\mingw64\bin\gcc.exe -DCMAKE_CXX_COMPILER:FILEPATH=D:\Software\mingw64\bin\g++.exe -SF:/OpenDemo/1_vsc_cmake -Bf:/OpenDemo/1_vsc_cmake/build -G "MinGW Makefiles"
@REM cmake -Bbuild -G "Visual Studio 17 2022" @REM cmake -Bbuild -G "Visual Studio 17 2022"
del ".\\build\\release\\bin\\demo.exe"
cmake -B build -G "MinGW Makefiles" cmake -B build -G "MinGW Makefiles"
make -C build make -C build
@ -10,4 +12,4 @@ make -C build test
@REM cpack -C ./build/CPackConfig.cmake @REM cpack -C ./build/CPackConfig.cmake
@REM cpack -C ./build/CPackSourceConfig.cmake @REM cpack -C ./build/CPackSourceConfig.cmake
"build/release/bin/demo.exe" ".\\build\\release\\bin\\demo.exe"