C++多态

多态原理

当类存在虚函数时,编译器会为该类维护一个表,这个表就是虚函数表(vtbl),里面存放了该类虚函数的函数指针。在构造类的时候增加一个虚表指针(vptr)指向对应的虚函数表。在类执行成员函数时候,先判断该函数是否是虚函数,如果不是虚函数则直接执行对应的方法,如果是虚函数则从虚函数表中找到应该调用的函数。

  • vptr的初始化是在类的构造时候完成。而在进行父类构造的时候,vptr指向的是父类vtbl。执行完子类的构造函数后,vptr在指向子类的btbl。
  • 父类指针(引用)指向子类进行多态调用时候,编译器并不关系是子类还是父类,而是通过vptr指向的btbl来找到对应的函数指针,并调用函数。
  • vtbl由编译器来维护

重载、覆盖、隐藏的区别和执行方式

4.1成员函数被重载的特征
(1)相同的范围(在同一个类中);
(2)函数名字相同;
(3)参数不同;
(4)virtual 关键字可有可无。
4.2“覆盖”是指派生类函数覆盖基类函数,特征是:
(1)不同的范围(分别位于派生类与基类);
(2)函数名字相同;
(3)参数相同;
(4)基类函数必须有virtual 关键字。
4.3“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,特征是:

(1)如果派生类的函数与基类的函数同名,但是参数不同,此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。
(2)如果派生类的函数与基类的函数同名,但是参数相同,但是基类函数没有virtual 关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)。

小结:说白了就是如果派生类和基类的函数名和参数都相同,属于覆盖,这是可以理解的吧,完全一样当然要覆盖了;如果只是函数名相同,参数并不相同,则属于隐藏。

示例

class Parent {
public:
    int x;

    Parent(int x) {
        this->x = x;
    }

     void print() {
        cout << "Parent " << x << endl;
    }
};

class Children : public Parent {
public:

    Children(int x) : Parent(x) {

    }

     void print() {
        cout << "Children " << x << endl;
    }
};

int main() {
    Parent *parent = NULL;
    Parent p(1);
    Children c(10);
    parent = &p;
    parent->print();
    parent = &c;
    parent->print();
}

测试一运行结果,发现虽然父类指针或引用指向了子类,但是在调用方法时候还是调用的父类的方法

Parent 1
Parent 10

测试二,对print方法加上virtual关键字,这时才体现出多态

Parent 1
Children 10

你可能感兴趣的:(C++多态)