2.关于多态

来源:互联网 发布:top域名值得投资吗? 编辑:程序博客网 时间:2024/06/06 02:29

这个问题出自联影的面试官

我跟很多人一样都犯了错,认为重载跟重写都是多态的实现方式。


实现多态的关键:虚函数


这里引用一段别人的对多态原理的解释:

当实例化一个该类的子类对象的时候,(如果)该类的子类并没有定义虚函数,但是却从父类中继承了虚函数,所以在实例化该类子类对象的时候也会产生一个虚函数表,这个虚函数表是子类的虚函数表,但是记录的子类的虚函数地址却是与父类的是一样的。所以通过子类对象的虚函数表指针找到自己的虚函数表,在自己的虚函数表找到的要执行的函数指针也是父类的相应函数入口的地址。

        如果我们在子类中定义了从父类继承来的虚函数,对于父类来说情况是不变的,对于子类来说它的虚函数表与之前的虚函数表是一样的,但是此时子类定义了自己的(从父类那继承来的)相应函数,所以它的虚函数表当中管于这个函数的指针就会覆盖掉原有的指向父类函数的指针的值,换句话说就是指向了自己定义的相应函数,这样如果用父类的指针,指向子类的对象,就会通过子类对象当中的虚函数表指针找到子类的虚函数表,从而通过子类的虚函数表找到子类的相应虚函数地址,而此时的地址已经是该函数自己定义的虚函数入口地址,而不是父类的相应虚函数入口地址,所以执行的将会是子类当中的虚函数。这就是多态的原理。

下面是代码验证,顺便复习一下构造和析构函数:

#include <iostream>using namespace std;class Base{public:Base(){ cout << "Base()" << endl; }virtual void a(int x){ cout << "Base::a(int)" << endl; }virtual void a(double x){ cout << "Base::a(double)" << endl; }virtual void b(int x){ cout << "Base::b(int)" << endl; }void c(int x){ cout << "Base::c(int)" << endl; }~Base() { cout << "~Base()" << endl; }};class Derived : public Base{public:Derived() { cout << "Derived()" << endl; }void a(char x){ cout << "Derived::a(char)" << endl; }void b(int x){ cout << "Derived::b(int)" << endl; }void c(int x){ cout << "Derived::c(int)" << endl; }~Derived() { cout << "~Derived()" << endl; }};int main(){Base b;Derived d;Base * pb = new Derived;b.a(1.0);d.a(1.0);pb->a(1.0);b.b(10);d.b(10);pb->b(10);delete pb;return 0;}


最后是运行结果: