多态原理
1、多态发生条件
a.子类继承父类,并且子类重写父类中虚函数
b.使用时,父类指针或者引用指向子类对象
此时父类指针调用相关函数发生动态多态
注意:
(1) 子类中的重写虚函数也可以是虚函数(virtual)
(2) 静态多态在编译时绑定,动态多态在运行时绑定
2、多态实现原理
首先,多态实现过程中,父类包含虚函数,创建父类对象是会生成一个虚函数表指针,指向父类的虚函数表;
子类继承父类,因此创建子类对象时子类对象也会生成虚函数表指针指向子类的虚函数表;
类的虚函数表类似类的static成员变量,共有的,属于类而不属于单个对象
父类和子类的虚函数表(肯定)不是同一个
虚函数表中存放虚函数的函数入口地址,子类继承父类的虚函数表,而又重写虚函数,因此子类中虚函数表中虚函数地址和父类中不是同一个,是各自成员函数入口地址(如:Animal类虚函数表中有存放父类成员函数speak的入口地址,子类Cat继承Animal类的虚函数表(此时虚函数表还完全相同),然后Cat重写speak函数,子类的speak函数的入口地址会代替子类中之前的speak函数的入口地址,自此,类Animal和Cat中虚函数表中存放的是他们各自的speak函数入口地址)
使用时,父类指针或引用指向子类,调用函数自然是子类的speak函数
多态时能调用的函数一定是父类中有的成员函数,若该函数在父类为虚函数且在子类中重写则调用的是重写后的函数,其他情况调用均是父类中成员函数
补充:空类大小为1
在C++语言中的确规定了空结构体和空类所占内存大小为1(而C语言中空类和空结构体占用的大小是0)
如果允许C++对象大小为0,那么这里的运算将产生两个问题:
(1)不能通过指针区分不同的数组对象(因为对象大小为0,所有数组对象同一个地址);
(2)sizeof T为0导致非法的除0操作。
故一般编译器使用一个字节来区分空类(或者结构体)。