Подтвердить что ты не робот

Параметры по умолчанию для виртуальных функций

Может ли кто-нибудь объяснить, где компиляторы С++ сохраняют значения по умолчанию для параметров для виртуальных функций? Я знаю, что это плохая идея изменить эти параметры в дочерних классах, но почему?  Спасибо.

4b9b3361

Ответ 1

Это плохая идея, потому что они нигде не хранятся.

Используемые значения по умолчанию будут такими, которые определены в статическом (время компиляции). Поэтому, если вы изменили параметры по умолчанию в переопределении, но вы вызвали функцию через указатель или ссылку базового класса, будут использоваться значения по умолчанию в базе.

#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;
}

Ответ 2

Предоставление инициализаторов аргументов по умолчанию виртуальных функций имеет тенденцию побеждать полиморфизм и вводить излишнюю сложность в иерархию классов.

рассмотрим следующий несовместимый код

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 не ясна. Предположительно, важно, чтобы значение по умолчанию для doItThisHigh для объекта типа MyThing равно 2.2. Однако неясно, должно ли это значение также использоваться по умолчанию при манипулировании MyThing через его интерфейс Thing.

Подробнее см. ниже ссылку https://www.securecoding.cert.org/confluence/display/cplusplus/OOP04-CPP.+Prefer+not+to+give+virtual+functions+default+argument+initializers