本文适合会C语言,并了解面向对面思想的同志。如果连多态还 不了解的话,就可以不用看了;
代码为随手打的,看思路为紧,下面说的类就是结构体
面向对象三要素:封装,继承,多态,
1:先说封装
:假设A类有成员变量int ,成员函数void fun(), 没有实现的成员函数 void fun2(),相当于一个虚函数
实现就是struct而已,成员函数用函数指针实现.
typedef struct A{ int x; void (*fun)(); void (*fun2)(); //在这个代码段没有给这个函数指针赋值(看A_init函数),相当于这是一个虚函数。 }A; void fun(A *this) { printf("调用A类成员变量X = %d\n",this->x); } 类A的init函数 ,可以理解为构造函数 void A_init( A* this ) { this->x = 0; this->fun = &fun(); }
封装还是很简单的。
2:继承
假设有上面的A类, B类继承至A类,则在B类中创建 A类成员(实际是struct 成员)就行了,同时实现类A未实现的函数fun2,可以理解为实现虚函数.
typedef struct B { int y; struct A a; //建议声明在开头,这里是为了体现offsetof 的妙用 }B; void fun2(A *this) { printf(“实现父类A的虚函数fun2 成员变量X=%d\n”,this->x); } void B_init(Struct B * this) //可以理解为B的构造函数 { A_init(& this->a ); //调用A的构造函数 this->y = 0; this->a.fun2 = fun2; //实现类A的虚函数 }
没错,上面就是继承,不然你以为有多复杂嘛
3:多态
多态的实现就是子类向上转型,和父类的向下转型(通过上面的虚函数,你应该有一点想法了吧),这里要介绍宏 offsetof. 当然也可以自己实现这个宏: 作用仅仅是算出结构体成员相对结构体开头的偏移量。
#define offsetof(TYPE,MEMBER) (size_t)&((TYPE *)0)->MEMBER)
也可以用container_of替换,详细请移步:https://blog.csdn.net/GouplovXim1314/article/details/80445287
3.1 向上转型
当你向上或向下转型时,说明你已经实现了基类A的虚函数fun2(),不同的子类有不同的实现,实质是函数指针指向的函数不同.
//在上面继承出,我们并没有对虚函数fun2()做该改变(向下转型),这使得我们无法使用类B的变量y,所以我们在这里重新构建类B,让大家看到多态的威力。
//以下代码与上面的代码无关
//**********************************类A
typedef struct A{
int x;
void (*fun)();
void (*fun2)(); //在这个代码段没有给这个函数指针赋值(看A_init函数),相当于这是一个虚函数。
}A;
void fun(A *this)
{
printf("调用A类成员变量X = %d\n",this->x);
}
类A的init函数 ,可以理解为构造函数
void A_init( A* this )
{
this->x = 0;
this->fun = &fun();
}
//************************************类A结束
//************************************类B,继承至类A
typedef struct B
{
int y;
struct A a; //建议声明在开头,这里是为了体现offsetof 的妙用
}B;
void B_fun2(A *this) //对虚虚函数有改变
{
//向下转型到B,
//请大家思考:为什么先把this转为char *,
B *b_p = (B *)(char *)this - offsetof(B,a);
//在这么,我就可以调用B的函数和变量了
printf(“实现父类A的虚函数fun2 A成员变量X=%d,B成员变量Y= %d\n”,this->x,b_p->y);
}
void B_init(Struct B * this) //可以理解为B的构造函数
{
A_init(& this->a ); //调用A的构造函数
this->y = 0;
this->a.fun2 = B_fun2; //实现类A的虚函数
}
//**************************************类B结束
//************************************类C,继承至类A
typedef struct C
{
int Z;
struct A a; //建议声明在开头,这里是为了体现offsetof 的妙用
}C;
void C_fun2(A *this) //对虚虚函数有改变
{
//向下转型到C,
//请大家思考:为什么先把this转为char *,
C *C_p = (C *)(char *)this - offsetof(C,a);
//在这么,我就可以调用C的函数和变量了
printf(“实现父类A的虚函数fun2 A成员变量X=%d,C成员变量Z= %d\n”,this->x,C_p->Z);
}
void C_init(Struct C * this) //可以理解为B的构造函数
{
A_init(& this->a ); //调用A的构造函数
this->Z = 0;
this->a.fun2 = C_fun2; //实现类A的虚函数
}
//**************************************类B结束
//感受多态的威力吧
int main()
{
struct B b;
B_init( &b ); //在B的 init函数中会调用 A 的init函数
struct C c;
C_init(&c);
//向上转型
struct A *a_p = (Struct A *)offsetof(B,a);
a_p->fun2(); //调用的是B_fun2;
a_p = (Struct A *)offsetof(C,a);
a_p->fun2(); //调用的是C_fun2;
return 0;
}
以上为大概思路,建议大家看看LW_OOPC 库,简单又有技巧,对于深入理解 C 和 面向对象高级语言的底层原理 有帮助。
假设你已经会了多态,那么进一步就是用C语言实现基础的设计模式(比如工厂模式),不然你学面向对象干嘛呢。