C++基础之三大特性之多态(顾客,别走啊,我这是羊肉,不是狗肉啊)

来源:互联网 发布:javastring转char数组 编辑:程序博客网 时间:2024/06/10 03:26

多态:多种形态

举个例子,你有两个fun函数,第一个类中fun的功能是打印1,第二个类的fun的功能是打印2,你建一个类的对象,调fun,想打印1就能打印1,想打印2就能打印2,这就是多态,这就是多种形态,这也就是我们代码中需要达到的要求

多态的本质:灵活的复用

多态的前提:继承的基础上

多态的实现:虚函数(有的人把重载这些也当作多态,静态的多态,这种东西看个人理解,不用扣这些字眼,下面才是重中之重---虚函数)

虚函数关键字:virtual

知识点一:

class A {  public:  virtual void fun(){printf("1");} };
class B : public A{ void fun(){printf("2");}};
B *p = new B; p->fun();

需求:不碰最后一行代码,怎么能调到A中的fun();

我们讲一下虚函数的原理

当类中有虚函数,建类的对象,对象空间的前四个字节放的是虚表地址,通过虚表地址找到虚表,虚表中有这个类的所有虚函数的地址

当继承有虚函数的类后,例如上面的B类,B类对象的前四个字节就有字节的虚表,如果B类有自己的虚函数,B类对象前四个字节是虚表的地址,地址找到的是自己类的虚函数地址----如果B类没有自己类的虚函数,它仍有虚表(继承),虚表找到的虚函数地址是父类(即上面A类)虚函数

(这里常人的误区:子类没有重写父类的虚函数,那子类的虚表是父类的虚表,子类虚表地址和父类虚表地址一样

在刚刚,2014-11-19的18:30时发现,子类虚表与父类虚表内容一样,仍旧指向父类的虚函数地址,但子类虚表的地址和父类虚表

的地址不一样,我现在新写一篇来详细介绍,这段话下面第二幅图片B类对象中的“A类虚表地址改为B类虚表地址即可”)

的地址

那如果要改上面的情况,只要把B类的fun函数擦掉就可以了

知识点二:

有没有注意到我子类的fun前面也加了虚函数的关键字呢,这是个技巧

防止作用

如果有一天有一个C类继承了我现在的子类B类,那B类就成了父类,建了C类的对象,C类对象有自己的fun函数,我的要求是调用C类的fun函数,但是如果有人捣乱或者不清楚,将得到C类对象地址的指针强转成B类的指针,调到的就是B类的fun函数了

知识点三:虚析构(应付下面这种情况)

下面这道题有什么问题吗

class A{       A::A()                      class B{           B::B()                            A *t = new B;char *p;       { p = new char[10];}        char *p;           { p = new char[10]; }              delete t;public:        A::~A()                     public:            B::~B()A();           { delete p; }               B();               { delete p; }~A();                                      ~B();};                                           };


我们看一下反汇编


这里Cs是子类,就是上面的B,上面的代码执行汇编是这样,看到01001757行代码调用子类的析构

所以这道题是B类的成员指针new出的空间泄漏了

当我们将父类的析构函数前加个virtual再看汇编

01001878调用的edx里面的内容在子类析构后最后调父类的析构

虚析构,调子类的析构---调父类析构

顺序为什么是先子后父呢---你要子类还用着,就析构了父类不就野指针了~~

虚析构是个好习惯

知识点四:纯虚函数

虚函数声明的时候后面写 = 0,这个类就是抽象类,这个函数就是纯虚函数

拥有纯虚函数的类不能建对象

如果HR问我纯虚函数,我就说 =0和不能建这个类的对象,我不会说抽象类这些概念,什么叫抽象

什么时候用到纯虚函数,就是这个类你确定以后不会建对象了,就写成纯虚函数

知识点五:声明虚函数的顺序影响虚函数在虚表中的位置

举例:一个类里有多个虚函数,声明的顺序,对应在虚表中的顺序

(实际也没有虚表这种东西,就是把所有的虚函数放在另一个地方,感觉这种结构像个表一样)

0 0
原创粉丝点击