多态时什么时候调用的是基类的虚函数

167 阅读1分钟
  • 构造函数中的虚函数

不要再构造函数内调用虚函数,此时派生类对象还未被构造出来,因此调用的是基类的虚函数。

#include<iostream>
using namespace std;
class MClass1{
public:
    MClass1(){func();};
    ~MClass1(){};
    virtual void func(){
        cout<<"MClass1\n";
    };
};
class MClass2:public MClass1{
public:
    MClass2(){func();};
    ~MClass2(){};
    void func()override{
        cout<<"MClass2\n";
    };
};
int main(){
    MClass1* m = new MClass2();
}

运行结果如下图所示:

2

  • 析构函数中的虚函数

派生类对象在基类析构函数执行前已被销毁,因此调用的是基类的虚函数。

#include<iostream>
using namespace std;
class MClass1{
public:
    MClass1(){};
    ~MClass1(){func();};
    virtual void func(){
        cout<<"MClass1\n";
    };
};
class MClass2:public MClass1{
public:
    MClass2(){};
    ~MClass2(){func();};
    void func()override{
        cout<<"MClass2\n";
    };
};
int main(){
    MClass1* m = new MClass2();
    delete m;
}

运行结果如下图所示:

1

  • 虚函数中的默认形参由静态类型决定

即使实际运行的是派生类中的函数,传入函数的也是基类函数定义地默认实参。

#include<iostream>
using namespace std;
class MClass1{
public:
    MClass1(){};
    ~MClass1(){};
    virtual void func(int a=10){
        cout<<"MClass1\n";
        cout<<"a = "<<a<<endl;
    };
};
class MClass2:public MClass1{
public:
    MClass2(){};
    ~MClass2(){};
    void func(int a=20)override{
        cout<<"MClass2\n";
        cout<<"a = "<<a<<endl;
    };
};
int main(){
    MClass1* m = new MClass2();
    m->func();
    delete m;
}

运行结果如下:

3

  • 结论
    • 不要在构造函数内调用virtual函数。
    • 如果虚函数使用默认实参,则基类和派生类的默认实参最好一致。