用c实现cpp三大特性

Cpp的三大特性:封装,继承,多态

封装

  • 类是数据封装的工具,对象是数据封装的实现。在封装中,还提供了一种对数据访问的控制机制,使得一些数据被隐藏在封装体内。封装体与外界进行信息交换是通过操作接口进行的。
  • 封装性实际上是由编译器去识别 public,private,protected 来实现的。只有类体内的成员函数才能访问私有成员,在类体外的函数不能访问。公有成员是封装体与外界的一个接口,类体外的函数可以访问公有成员,保护成员只有该类的派生类可以访问。
  • 类是一种复杂的数据类型,他将不同类型的数据和相关操作封在一起的集合体。因此类具有对数据的抽象性,隐蔽性和封装性。
  • 封装目的是为了增加代码的健壮性,减少写代码时出错的概率。只要编译可以通过,在 C++ 中无论是 public,private,protect,生成的汇编代码都是一样的。

继承

  • C++ 允许单继承和多继承。
  • 继承机制的目的时为了可以重复使用程序资源。
  • 继承有两个方面,一是可以拥有父类的所有成员变量,第二子类也拥有父类的所有成员函数

多态

  • 多态是指,对不同类对象发出相同消息,会有不同的实现。多态是指发出同样的消息被不同的数据类型的对象接受后导致不同的行为。
  • C++ 多态表现为:
  1. 允许函数重载和运算符重载。
  2. 通过定义虚函数来支持动态联编。
  • 多态特性增加了一些数据存储和执行指令开销,能不用就不用。

C代码实现

定义函数指针

1
2
3
4
5
6
7
8
9
10
11
12
int add(int a, int b) {
return a + b;
}

// 定义函数指针
int (*padd)(int, int);
padd = add;

// 用typedef重命名
typedef int (*PADD)(int, int);
PADD padd;
padd = add;

继承和多态代码

简单实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <stdio.h>
//C语言模拟C++的继承与多态
typedef void (*FUN)(); //定义一个函数指针来实现对成员函数的继承
typedef struct _A { //父类
FUN _fun; //由于C语言中结构体不能包含函数,故只能用函数指针在外面实现
int _a;
} _A;

typedef struct _B { //子类
_A _a_; //在子类中定义一个基类的对象即可实现对父类的继承
int _b;
} _B;

void _fA() { //父类的同名函数
printf("_A:_fun()\n");
}
void _fB() { //子类的同名函数
printf("_B:_fun()\n");
}

int main() {
//C语言模拟继承与多态的测试
_A _a; //定义一个父类对象_a
_B _b; //定义一个子类对象_b
_a._fun = _fA; //父类的对象调用父类的同名函数
_b._a_._fun = _fB; //子类的对象调用子类的同名函数

_A* p2 = &_a; //定义一个父类指针指向父类的对象
p2->_fun(); //调用父类的同名函数
p2 = (_A*)&_b; //让父类指针指向子类的对象,由于类型不匹配所以要进行强转
p2->_fun(); //调用子类的同名函数
}

结果:

1
2
3
@└────> # ./a.out
_A:_fun()
_B:_fun()

虚函数表实现方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <stdio.h>
#include <string.h>
typedef void(*funcP)(void*);
typedef void*(*virTabPointer)[2]; //这是一个指针
typedef struct Animal {
//指向虚函数表的指针
virTabPointer m_virPointer;
char m_name[20];
} Animal;

typedef struct Tiger {
Animal m_base; // 继承基类
int m_age;
} Tiger;

typedef struct Bull {
Animal m_base; // 继承基类
char m_sex[6];
} Bull;

void SayName(void* this) {
Animal* thisA = (Animal*)(this); // 强转为基类
printf("我的名字是:%s\n", thisA->m_name);
}

void TigerEat(void* this) { // Tiger成员函数
Animal* thisA = (Animal*)(this);
printf("我的名字是:%s,", thisA->m_name);
Tiger* thisTiger = (Tiger*)(this);
printf("今年%d岁,我吃肉\n", thisTiger->m_age);
}

void BullEat(void* this) { // Bull成员函数
Animal* thisA = (Animal*)(this);
printf("我的名字是:%s,", thisA->m_name);
Bull* thisBull = (Bull*)(this);
printf("我的性别是:%s,我吃草\n", thisBull->m_sex);
}

void TemplateFunc(Animal* obj) { // 此函数用于调用子类的特有函数
//do something
void** tempIntPointer = (void**)(obj); // 取首地址
virTabPointer tempVTab = (virTabPointer)(*tempIntPointer); // 取虚表地址
funcP tempFuncAddress = (funcP)((*tempVTab)[1]);
tempFuncAddress(obj);
}

//指针的数组,数组中的所有元素都是指针,是个数组
void* animalVirTab[2] = {(void*)&SayName, NULL};
void* tigerVirTab[2] = {(void*)&SayName, (void*)&TigerEat}; // 有几个虚函数元素长度就是几
void* bullVirTab[2] = {(void*)&SayName, (void*)&BullEat}; // 有几个虚函数元素长度就是几

int main() {
Animal* basePointer = NULL; //基类的指针
// Tiger多态
Tiger tigerA;
basePointer = (Animal*)&tigerA;
strcpy(basePointer->m_name, "老虎");
basePointer->m_virPointer = &tigerVirTab;
tigerA.m_age = 5;
TemplateFunc(basePointer);
// Bull多态
Bull bullA;
basePointer = (Animal*)&bullA;
strcpy(basePointer->m_name, "牛");
basePointer->m_virPointer = &bullVirTab;
strcpy(bullA.m_sex, "男");
TemplateFunc(basePointer);
return 0;
}

结果:

1
2
3
@└────> # ./a.out
我的名字是:老虎,今年5岁,我吃肉
我的名字是:牛,我的性别是:男,我吃草