多态的通用描述便是,使用父类指针调用函数,可以根据对象类型来调用对应类型函数,我们分几个步骤来理解,先看下类的占用空间,然后拓展到虚函数对应数组,最后理解多态的原理。
我们先来看下在多态中没有任何成员变量的类大小为多大,其实如果没有任何成员变量的话,他大小按理说来应该是零,但是为了限制无限创建类,还是需要用一个占位符,见以下代码:
#include<iostream>
using namespace std;class ami {
public:void eat() {cout << "动物吃。。" << endl;}
};class cat1 : public ami{
public:void eat() {cout << "咪咪吃。。" << endl;}
};void eat(ami& m) {m.eat(); //3
}void Test() {cat1 d; eat(d); // 2cout << "ami size is " << sizeof(ami) << endl;
}int main() {Test();// 1return 0;
}
运行结果见下:
从监视也可以看出,确实没有保存内容,只是提供一个占位
如果是加上虚函数,我们再来看下类的大小
#include<iostream>
using namespace std;class ami {
public:virtual void eat() {cout << "动物吃。。" << endl;}
};class cat1 : public ami{
public:void eat() {cout << "咪咪吃。。" << endl;}
};void eat(ami& m) {m.eat(); //3
}void Test() {cat1 d; eat(d); // 2cout << "ami size is " << sizeof(ami) << endl;
}int main() {Test();// 1return 0;
}
看下运行结果
我们再来看下监视的内容,这里的八个字节其实是虚函数指针,这个指向一个数组首地址,由虚函数组成的数组:
我们再看另一种情况
#include<iostream>
using namespace std;class ami {
public:virtual void eat() {cout << "动物吃。。" << endl;}virtual void run() {cout << "动物跑。。" << endl;}
};class cat1 : public ami{
public:void eat() {cout << "咪咪吃。。" << endl;}
};void eat(ami& m) {ami f;m.eat(); //3
}void Test() {cat1 d; eat(d); // 2cout << "ami size is " << sizeof(ami) << endl;
}int main() {Test();// 1return 0;
}
我们来看下监视的内容:
如果是继承的时候,子类覆盖掉父类对应的虚函数即可,换句话说,子类在继承父类函数时,直接到虚函数列表中去找,直接找已经覆盖掉的父类函数。这个也是为啥说会产生一个虚函数列表,这个是为了方便多态。这个便是多态的原理,直接从数组中找对应函数(并且是已经覆盖了的父类函数)。