C++ 虚函数的默认参数问题

C++缺省参数问题

一般函数

  • 有函数声明时,默认参数可以放在函数声明或者定义中,但只能放在二者之一,建议放在声明中

  • 没有函数(原型)时,默认参数在函数定义时指定

    static void Test0(int a = 0);
    ...
    void Test0(int a) {
        cout << a << endl;
    }
    ...
    void Test1(int a, int b = 2, char c = '3', string d = "4") {
        cout << a << endl << b << endl << c << endl << d << endl;
    }
    
  • 一旦某个参数开始指定默认值,它右边的所有参数都必须指定默认值:函数声明时,必须按照从右向左的顺序,依次给与默认值

  • 在调用具有默认参数的函数时,若某个有默认参数的参数使用了默认参数, 它右边的所有参数都使用默认参数:函数调用时,必须按照从左向右的顺序,依次赋值

    #include<bits/stdc++.h>
    
    using namespace std;
    
    static void Test0(int a = 0);
    static void Test1(int a, int b = 2, char c = '3', string d = "4");
    
    int main() {
        Test0();
        Test1(1);
        //'2'会转换成int,执行Test1
        Test1(1, '2');
        return 0;
    }
    
    void Test0(int a) {
        cout << a << endl;
    }
    
    void Test1(int a, int b, char c, string d) {
        cout << a << endl << b << endl << c << endl << d << endl;
    }
    

类的一般成员函数

  • 同上

类的虚函数

结论:决不要重新定义继承而来的缺省参数值

#include<bits/stdc++.h>
using namespace std;

class A {
public:
    virtual void Test0(int a = 5) = 0;
};

class B : public A {
public:
    virtual void Test0(int a = 6) override {
        cout << a << endl;
    }
};

int main() {
    A* a = new B();
    a->Test0();
    return 0;
}

原因:

  • 虚函数是动态绑定的,即具体被调用的虚函数由那个对象的动态类型决定

  • 缺省参数是静态绑定的,即编译阶段就确定了虚函数的默认参数一定来自Base类;

    这样做的原因是:运行效率。如果缺省参数被动态绑定,需要类似查虚表的机制,这将比现在采用的在编译阶段确定缺省值的机制更慢更复杂

    比如:上方代码如果调用Test0()

    • 参数压栈

    • 返回地址压栈

    • 调用函数:因为虚函数,需要虚表找到函数指针,跳到函数实际地址执行函数

      注意到此时参数已经压栈,虽然可以用类似的机制实现动态绑定,但没必要

posted @ 2021-04-19 23:48  Jamgun  阅读(946)  评论(2编辑  收藏  举报