Expressions and statements
ES.63
Не допускайте срезки объектов
Причина
Срезка — то есть копирование лишь части объекта при присваивании или инициализации — в большинстве случаев приводит к ошибкам, поскольку объект предполагалось рассматривать целиком. В редких случаях, когда срезка намеренна, код выглядит удивительно.
Пример
class Shape { /* ... */ };
class Circle : public Shape { /* ... */ Point c; int r; };
Circle c { {0, 0}, 42 };
Shape s {c}; // копируется только часть Shape из Circle
s = c; // или копируется только часть Shape из Circle
void assign(const Shape& src, Shape& dest)
{
dest = src;
}
Circle c2 { {1, 1}, 43 };
assign(c, c2); // упс: передаётся не всё состояние
assert(c == c2); // если поддерживается копирование, нужно поддерживать и сравнение,
// но, скорее всего, вернёт false
Результат будет бессмысленным, так как центр и радиус не скопируются из c в s. Первая защита от этого — запрет подобного поведения в определении базового класса Shape.
Альтернатива
Если срезка намеренна, определите явную операцию для её выполнения. Это избавит читателей от путаницы. Например:
class Smiley : public Circle {
public:
Circle copy_circle();
// ...
};
Smiley sm { /* ... */ };
Circle c1 {sm}; // в идеале запрещено определением Circle
Circle c2 {sm.copy_circle()};
Контроль
Предупреждать о срезке.