1

In the CppCoreGuidelines item C.21, this example shows the copy/move special functions being declared =default in an AbstractBase class. It then goes on to say

Alternatively to prevent slicing as per C.67, the copy and move operations can all be deleted

and provides a second example with the functions declared with =delete.

If I have a class that is intended to be a base class in an inheritance hierarchy, should I always use the second example and delete the copy/move special functions to prevent slicing? Why would I use =default instead, if it opens the class up to errors?

ToddR
  • 300
  • 1
  • 11
  • It depends. Do you want people to be able to make copies of your objects? – NathanOliver Oct 01 '18 at 18:53
  • @NathanOliver Possibly, but others have recommended not using the special member functions even in that case, implementing a virtual `clone()` method instead, again due to slicing. – ToddR Oct 01 '18 at 19:02

1 Answers1

1

It all depends on your use case:

  • Slicing is a common cause of error when you use polymorphic classes, especially if you have code that makes heavy use of the polymorphic base class. It is then easy to accidentally copy/move/assign two object values that are then handled as if they were base classes. If this is your use case, then you should follow the advice. Typically, these kind of classes are best used via a (smart-)pointer and are cloned rather than copied.

  • If you have an abstract base class but you intend to use in most of the cases its derived classes, then there's no need to prevent slicing in this way, since there are much less risks of errors.

Christophe
  • 68,716
  • 7
  • 72
  • 138
  • In your second case, is there any down side to marking them `=delete`? I understand there may not be a need, but if it would automatically prevent slicing, why not do it anyway? – ToddR Oct 01 '18 at 19:49
  • @ToddR The downside of `=delete` is that you can't perform elementary operations and you would have to provide other means to achieve the needs to copy-construct or to assign. In the case of very polymorphic code it's justified. But in many case it's just an excess of prudence. You could for example no longer do `vector v=u;` because it would imply copying the individual elements in a vector and you've deleted this possibility. You could not use many standard algorithms either. So if you don't have a strong reason to delete, don't do it. – Christophe Oct 01 '18 at 20:27
  • 1
    In that case, wouldn't making them protected and defaulted achieve both? I wouldn't be able to copy/move using the base class (prevents slicing), but I would still be able to use them to implement the derived class copy/move. – ToddR Oct 01 '18 at 20:50
  • @ToddR yes, this could be an alternative: base class couldn't be for example copy-constructed, but the derived class could implement the copy constructor using the protected copy constructor of the base class. – Christophe Oct 01 '18 at 20:58