воскресенье, 1 сентября 2013 г.

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

Параметры по умолчанию связываются на этапе компиляции, а выбор виртуальной функции происходит на этапе выполнения, потому будет выбран параметр по умолчанию равный типу указателя (ссылки) через который вызывается виртуальная функция (т.е. тип базового класса, а не производного).
Причина: Если бы значения аргументов по умолчанию связывались динамически, то компилятору пришлось бы найти способ во время исполнения определять, какое значение по умолчанию должно быть у параметра виртуальной функции, что медленнее и технически сложнее нынешнего механизма. Решение было принято в пользу скорости и простоты реализации, в результате чего вы можете пользоваться преимуществами эффективного выполнения кода программы.

Пример:

class Shape {
public:
enum ShapeColor { Red, Green, Blue };
// все фигуры должны предоставлять функцию для рисования
virtual void draw(ShapeColor color = Red) const = 0;
...
};
class Rectangle: public Shape {
public:
// заметьте, другое значение параметра по умолчанию – плохо!
virtual void draw(ShapeColor color = Green) const;
...
};
class Circle: public Shape {
public:
virtual void draw(ShapeColor color) const;
...
};

Shape *ps; // статический тип – Shape*
Shape *pc = new Circle; // статический тип – Shape*
Shape *pr = new Rectangle; // статический тип – Shape*

pr->draw(); // вызывается Rectangle::draw(Shape::Red)!

Поскольку статический тип pr – Shape*, то значения аргумента по умолчанию берутся из класса Shape, а не Rectangle.
Решение: невиртуальная функция базового класса + NVI.

Источник: Скотт Мэйерс Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ.

По мотивам правила 37.

Комментариев нет:

Отправить комментарий