Параметры по умолчанию в С++ - это опасно

Значения формальных параметров по умолчанию в С++ - удобная штука. Удобная и опасная.

Вот книжный пример (default_values.cpp):

#include <iostream>

class X {
 public:
  virtual void f(int i = 0) {
    std::cout << "X::f(): " << i << std::endl;
  }
};

class Y: public X {
 public:
  void f(int i = 1) {
    std::cout << "Y::f(): " << i << std::endl;
  }
};

int main() {
  X* a = new Y;
  a->f();

  Y* b = new Y;
  b->f();

  return 0;
}

Что распечатает эта программа? Вот что:

Y::f(): 0
Y::f(): 1

В обоих случаях была вызвана функция Y::f(), но значение аргумента было разное.

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

Я намеренно опустил модификатор virtual в описании функции f() в классе Y. Но от этого она невиртуальной не стала. При сложной иерархии классов очень несложно не заметить, что изначально функция была виртуальной, и для собственного удобства подправить ей значение параметра по умолчанию для какого-то конкретного случая, тем самым привнеся очень неприятную ошибку (и тут уже надежда на зоркий глаз коллеги при code view или на статические анализаторы).

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

Посты и ссылки по теме:


Оригинальный пост | Disclaimer

Комментарии