CppCoreGuidelines
CppCoreGuidelines copied to clipboard
C.67: Does a class marked final prevent slicing?
Consider the following adapted example based on C.67: A polymorphic class should suppress public copy/move (there now is an additional class E derived from D and D does not comply with C.67).
class B { // GOOD: polymorphic class suppresses public copying
public:
B() = default;
virtual char m() { return 'B'; }
protected:
B(const B&) = default;
B& operator=(const B&) = default;
// ...
};
class D : public B { // BAD: polymorphic derived class doesn't suppress public copying
public:
char m() override { return 'D'; }
// No user-defined copy-constructor so according to cppreference (https://en.cppreference.com/w/cpp/language/copy_constructor) the compiler will implicitly generate a public copy constructor
// ...
};
class E : public D {
public:
char m() override { return 'E'; }
// ...
};
void f(B& b)
{
auto b2 = b; // ok, compiler will detect inadvertent copying, and protest
}
void g(D& d)
{
auto d2 = d; // oops, slices the object; d2.m() will return 'D'
}
E e;
g(e);
To my understanding, D is a polymorphic class in terms of C.67 as it inherits a virtual function. Slicing obviously occurs due to D not complying with C.67.
My question now is, what if there should not be any classes derived from D in the first place? I.e. D being introduced in the following way:
class D final : public B { // QUESTION: does final prevent slicing in function g?
public:
char m() override { return 'D'; }
// No user-defined copy-constructor so according to cppreference the compiler will implicitly generate a public copy constructor
// ...
};
Is it sound to mark D final and keep the implicitly generated public copy constructor (i.e. apply C.20: If you can avoid defining default operations, do in this case)? Or can this still lead to slicing in function g?