目录
定义:就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的状态。会使程序变得更简单。
①多态的形式:
(1)重载多态——函数重载——运算符重载
(2)包含多态——virtual函数
(3)参数多态——模板
(4)强制多态——强制类型转换(有四种) static_cast const_cast...②多态的条件:
(1)满足覆盖
(2)基类的指针或者引用指向基类对象或派生类对象
- 如果一个类包含了虚函数,不管有多少个虚函数,则只增加一个指针的大小;
- 有了一个VPtr(虚指针),VPtr指向一个虚表(vtable),虚表里面存储本类中虚函数的入口地址(可以把表格当成一个数组);
- 非虚函数1个字节,虚函数4个字节(当前一个指针的大小)。
- class A
- {
- public:
- //void ff() {}//非虚函数1个字节,虚函数4个字节(当前一个指针的大小)
- virtual void fa() { cout << "A::fa" << endl; }
- virtual void fb() { cout << "A::fb" << endl; }
- virtual void fc() { cout << "A::fc" << endl; }
- };
-
- int main()
- {
- //cout<
- A a;
- typedef void(*FUN)();
- /*a.fa();
- a.fb();
- a.fc();*/
- FUN pf = NULL;//pf是函数指针类型,先指向空
- (int*)(&a);//把a*强转为int*
- pf = (FUN) * ((int*)(*(int*)(&a)));
- pf();
- pf = (FUN) * ((int*)(*(int*)(&a))+1);
- pf();
- pf = (FUN) * ((int*)(*(int*)(&a))+2);
- pf();
-
- }
- class A
- {
- public:
- virtual void fa() { cout << "A::fa" << endl; }
- virtual void fb() { cout << "A::ga" << endl; }
- virtual void fc() { cout << "A::ha" << endl; }
- };
单继承步骤:
① 全盘接收:B把A的虚表直接继承,class B : public A。
②改写:改写A中的虚函数,改为B::fa。
③添加自己的函数:添加了两个自己的虚函数gb,hb。
注意:子类对象不能接收基类对象,子类对象比较多;
- //B可以调用5个函数:fa,ga,ha,gb,hb
- class B :public A//B把A的虚表直接继承过来
- {
- public:
- virtual void fa() { cout << "B::fa" << endl; }//改写A中的虚函数
- //添加两个虚函数
- virtual void gb() { cout << "B::gb" << endl; }
- virtual void hb() { cout << "B::hb" << endl; }
- };
-
- int main()
- {
- //cout<
- B b;
- typedef void(*FUN)();
- FUN pf = NULL;//pf是函数指针类型,先指向空
- //先给b取个地址
- pf = (FUN) * ((int*)(*(int*)(&b)));//B::fa
- pf();
- pf = (FUN) * ((int*)(*(int*)(&b)) + 1);//A::ga
- pf();
- pf = (FUN) * ((int*)(*(int*)(&b)) + 2);//A::ha
- pf();
- pf = (FUN) * ((int*)(*(int*)(&b)) + 3);//B::gb
- pf();
- pf = (FUN) * ((int*)(*(int*)(&b)) + 4);//B::hb
- pf();
-
- }
多继承:在子类的对象中,每个父类都有自己的虚表,将最终子类的虚函数放在第一个,
父类的虚表中,这样做解决了不同的父类类型的指针指向比较清晰。
如果在子类中重写了多个父类的同名同参虚函数,那么在虚表中同样做了修改。
- class A
- {
- public:
- virtual void ff() { cout << "A::ff" << endl; }
- virtual void ha() { cout << "A::ha" << endl; }
- };
- class B
- {
- public:
- virtual void ff() { cout << "B::ff" << endl; }
- virtual void hb() { cout << "B::hb" << endl; }
- };
-
- class C
- {
- public:
- virtual void ff() { cout << "C::ff" << endl; }
- virtual void hc() { cout << "C::hc" << endl; }
- };
-
- //D继承了三个虚表,谁先继承就挂谁(内存里面)
- class D:public A,public B,public C
- {
- public:
- virtual void ff() { cout << "D::fd" << endl; }
- virtual void hd() { cout << "D::hd" << endl; }
- };
-
- int main()
- {
- cout << sizeof(D) << endl;//12
- D d;
- typedef void(*FUN)();
- FUN pf = NULL;//pf是函数指针类型,先指向空
- pf = (FUN) * ((int*)*(int*)(&d));//
- pf();
- pf = (FUN) * ((int*)*(int*)(&d) + 1);//
- pf();
- pf = (FUN) * ((int*)*(int*)(&d) + 2);//
- pf();
- cout << "第二张虚表" << endl;
- pf = (FUN) * ((int*)*(int*)(&d) + 3);//
- pf();
- pf = (FUN) * ((int*)*(int*)((int*)(&d)+ 1));//
- pf();
- pf = (FUN) * ((int*)*(int*)((int*)(&d) + 1)+1);//
- pf();
- pf = (FUN) * ((int*)*(int*)((int*)(&d) + 1)+2);//
- pf();
-
-
- }
覆盖(重写):是指同名同参的函数。
- 最少两个类,必须是父子关系
- 必须是同名同参虚函数,基类写了virtual虚函数,子类里可以不写(子类继承)
(1)定义:
联编:是指计算机程序彼此关联的过程,(使一个源程序经过编译、连接,成为一个可执行程序)的过程;在这个联编过程中,需要确定程序中的操作调用(函数调用)与执行该操作函数)的代码段之间的映射关系。
(2)分类:
- 静态联编(是早期绑定)
- 动态联编
联编(捆绑,绑定)——函数调用和函数体联系的过程
早捆绑——在编译时
挖捆绑——在运行时
- class A
- {
- public:
- virtual void fn() { cout << "A::fn" << endl; }
- virtual void ff() { cout << "A::ff" << endl; }
- void fff() { cout << "A::fff" << endl; }
-
- };
- class B :public A//B把A的虚表直接继承过来
- {
- public:
- virtual void fn() { cout << "B::fn" << endl; }//改写A中的虚函数
- virtual void fb() { cout << "B::fb" << endl; }
- void fff() { cout << "A::fff" << endl; }
-
- };
-
- void test1(A* p)
- {
- p->fn();
- }
-
- void test(A& aa)
- {
- aa.fn();
- aa.ff();
- aa.fff();
- }
-
- int main()
- {
- A a;
- B b;
- test(a);
- test(b);
- test1(&a);
- test1(&b);
-
- }
如有错误,敬请指正。
您的收藏与点赞都是对我最大的鼓励和支持!