Стандарты программирования на С++


Обсуждение


Хотя обычно производные классы добавляют новые состояния (т.е. члены-данные), они моделируют подмножества (а не надмножества) своих базовых классов. При корректном наследовании производный класс моделирует частный случай более общей базовой концепции (см. рекомендацию 37).

Это имеет прямые следствия для корректного перекрытия функций. Соблюдение отношения включения влечет за собой заменимость — операции, которые применимы ко всему множеству, применимы и к любому его подмножеству. Если базовый класс гарантирует выполнение определенных пред- и постусловий некоторой операции, то и любой производный класс должен обеспечить их выполнение. Перекрытие может предъявлять меньше требований и предоставлять большую функциональность, но никогда не должно предъявлять большие требования или меньше обещать — поскольку это приведет к нарушению контракта с вызывающим кодом.

Определение в производном классе перекрытия, которое может быть неуспешным (например, генерировать исключения; см. рекомендацию 70), будет корректно только в том случае, когда в базовом классе не объявлено, что данная операция всегда успешна. Например, скажем, класс Emplоуее содержит виртуальную функцию-член GetBuilding, предназначение которой — вернуть код здания, в котором работает объект Emplоуее. Но что если мы захотим написать производный класс RemoteContractor, который перекрывает функцию GetBuilding, в результате чего она может генерировать исключения или возвращать нулевой код здания? Такое поведение корректно только в том случае, если в документации класса Employee указано, что функция GetBuilding может завершаться неуспешно, и в классе RemoteContractor сообщение о неудаче выполняется документированным в классе Emplоуее способом.

Никогда не изменяйте аргумент по умолчанию при перекрытии. Он не является частью сигнатуры функции, и клиентский код будет невольно передавать различные аргументы в функцию, в зависимости от того, какой узел иерархии обращается к ней. Рассмотрим следующий пример:

class Base { // ... virtual void Foo( int x = 0 ); };




Начало  Назад  Вперед



Книжный магазин