📅  最后修改于: 2023-12-03 15:29:52.056000             🧑  作者: Mango
在C++中,虚函数是一种特殊的成员函数,它可以被派生类重写,从而达到多态的效果。然而,在使用虚函数时也会遇到一些问题,本文将介绍其中的一个问题:虚函数的默认参数问题。
当虚函数带有默认参数时,如果在派生类中不显式地覆盖该虚函数,那么派生类实例化的对象调用默认参数时将会出现错误。
假设我们有如下的基类和派生类:
class Base {
public:
virtual void func(int a = 1) {
cout << "Base::func(" << a << ")" << endl;
}
};
class Derived : public Base {
public:
virtual void func(int a = 2) override {
cout << "Derived::func(" << a << ")" << endl;
}
};
在以上的代码中,基类Base
定义了一个func()
函数,该函数带有一个默认参数a = 1
,而派生类Derived
重写了该函数,并带有一个不同的默认参数a = 2
。
接下来,我们分别生成基类和派生类的对象,并调用它们的func()
函数:
int main() {
Base* b = new Base();
Derived* d = new Derived();
b->func(); // Base::func(1)
d->func(); // Derived::func(2)
delete b;
delete d;
return 0;
}
如果在使用派生类d
调用func()
时没有出现问题,我们会看到以下输出结果:
Base::func(1)
Derived::func(2)
如果我们将代码稍微改变一下,将基类指针指向派生类对象,再次调用func()
函数:
Base* p = new Derived();
p->func(); // Base::func(1)
我们会发现调用结果不符合我们的预期。派生类的func()
函数应该会被调用,并输出Derived::func(2)
,但实际上却输出了Base::func(1)
。这是因为在派生类中并没有显式地覆盖该虚函数的默认参数,所以虚函数的默认参数保留为基类的默认参数,即a = 1
,而非派生类的默认参数a = 2
。
为了解决虚函数默认参数的问题,我们需要在派生类中重载该函数,并显式地声明该函数的默认参数。例如,以下代码中我们将函数func()
的默认参数从1
改为3
:
class Derived : public Base {
public:
virtual void func(int a = 3) override {
cout << "Derived::func(" << a << ")" << endl;
}
};
现在,当我们将基类指针指向派生类对象再次调用func()
函数时,就会得到正确的输出结果:
Base* p = new Derived();
p->func(); // Derived::func(3)
虚函数是C++中非常重要的机制。在使用虚函数时,我们需要注意函数默认参数的问题,以免造成不必要的错误。当发现这类问题时,我们需要在派生类中显式地声明该函数的默认参数,以保证正确性。