虚函数默认参数

Lea*_*eaf 36 c++

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

zmb*_*zmb 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;
}
Run Code Online (Sandbox Code Playgroud)

  • 要了解它是如何工作的,默认值将填入调用站点(其中只知道静态类型),因此编译器实际上在编译时将`derived-> foo()`转换为`derived-> foo(0)`时间. (9认同)

Mah*_*esh 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 );
    // ...
};
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

在这段代码中,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