Expressions and statements
ES.63
Don't slice
Reason
Slicing -- that is, copying only part of an object using assignment or initialization -- most often leads to errors because the object was meant to be considered as a whole. In the rare cases where the slicing was deliberate the code can be surprising.
Example
class Shape { /* ... */ };
class Circle : public Shape { /* ... */ Point c; int r; };
Circle c { {0, 0}, 42 };
Shape s {c}; // copy construct only the Shape part of Circle
s = c; // or copy assign only the Shape part of Circle
void assign(const Shape& src, Shape& dest)
{
dest = src;
}
Circle c2 { {1, 1}, 43 };
assign(c, c2); // oops, not the whole state is transferred
assert(c == c2); // if we supply copying, we should also provide comparison,
// but this will likely return false
The result will be meaningless because the center and radius will not be copied from c into s. The first defense against this is to define the base class Shape not to allow this.
Alternative
If you mean to slice, define an explicit operation to do so. This saves readers from confusion. For example:
class Smiley : public Circle {
public:
Circle copy_circle();
// ...
};
Smiley sm { /* ... */ };
Circle c1 {sm}; // ideally prevented by the definition of Circle
Circle c2 {sm.copy_circle()};
Enforcement
Warn against slicing.