📜  C++ |虚函数|问题1(1)

📅  最后修改于: 2023-12-03 15:29:52.056000             🧑  作者: Mango

C++虚函数问题1

在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++中非常重要的机制。在使用虚函数时,我们需要注意函数默认参数的问题,以免造成不必要的错误。当发现这类问题时,我们需要在派生类中显式地声明该函数的默认参数,以保证正确性。