Вот книжный пример (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 или на статические анализаторы).При возрастающей сложности проекта гораздо важнее иметь надежные исходники, чем минутное локальное удобство.
Посты по теме:
- Google запрещает параметры по умолчанию для своих разработчиков
- Статический анализ кода (Coverity, Klocwork)
- Ведение блога на Google Code
Как я уже писал ранее, все исходные тексты и статьи теперь дублируются на одноименном сайте, размещенном на Google Code.
Молоток тоже опасен
ОтветитьУдалить