虚函数默认参数

时间:2013-08-07 14:02:35

标签: c++

有人可以解释c ++编译器在哪里保留虚函数参数的默认值?我知道在子类中更改这些参数是个坏主意,但为什么呢?  感谢。

2 个答案:

答案 0 :(得分:51)

这是一个坏主意,因为它们不会被放在任何地方。

使用的默认值将是静态(编译时)类型中定义的值。因此,如果您要更改覆盖中的默认参数,但是通过基类指针或引用调用了该函数,则将使用基础中的默认值。

#include <iostream>

struct Base
{
    virtual ~Base(){ }
    virtual void foo(int a=0) { std::cout << "base: " << a << std::endl; }
};

struct Derived : public Base
{
    virtual ~Derived() { }
    virtual void foo(int a=1) { std::cout << "derived: " << a << std::endl; }
};

int main()
{
    Base* derived = new Derived();
    derived->foo();    // prints "derived: 0"
    delete derived;
}

答案 1 :(得分:5)

为虚函数提供默认参数初始化程序往往会破坏多态性并在类层次结构中引入不必要的复杂性。

考虑以下不合规代码

class Thing {
  public:
    virtual ~Thing();
    virtual void doItNTimes( int numTimes = 10 );
    virtual void doItThisHigh( double howHigh = 1.0 );
    // ...
};
class MyThing : public Thing {
  public:
    void doItNTimes( int numTimes );
    void doItThisHigh( double howHigh = 2.2 );
    // ...
};

默认初始值设定项不是函数签名类型的一部分,不参与覆盖或隐藏。因此,将覆盖此非兼容代码示例中显示的两个基类虚函数在派生类中。但是,基类和派生类接口中的默认参数初始值设定项的状态不同会导致行为的差异,具体取决于用于访问对象的接口。

MyThing *mt = new MyThing;
Thing *t = mt;
t->doItNTimes(); // default of 10
mt->doItNTimes();  // compile time error!
t->doItThisHigh(); // default of 1.0!
mt->doItThisHigh(); // default of 2.2

在这段代码中,MyThing类的设计者的意图并不清楚。据推测,对于MyThing类型的对象,doItThisHigh的默认值为2.2非常重要。 但是,当通过Thing界面操作MyThing时,默认情况下是否也应该使用该值尚不清楚。

有关详细信息,请参阅以下链接https://www.securecoding.cert.org/confluence/display/cplusplus/OOP04-CPP.+Prefer+not+to+give+virtual+functions+default+argument+initializers