4

When implementing an abstract class like this:

class Base
{
public:
    virtual ~Base() = default;
    virtual void foo() = 0;
};

Does this interface have to obey the rule of five i.e. do I have to add a copy constructor, copy assignment operator, move constructor and move assignment operator?

I'd figure that an instace of type Base can not be instantiated due to the pure virtual member function and thus providing default implementations for the other special member functions might serve no real purpose.

Is there any use-case/example that would require me to provide the other special member functions?

  • 2
    How would you implement those constructor/operators? :P – Rakete1111 May 26 '18 at 16:31
  • You `default`ed your destructor, means you're telling the compiler to generate one. It should be no different to when you just do nothing. – Killzone Kid May 26 '18 at 16:41
  • 1
    @KillzoneKid But I guess the intent is that the destructor be virtual. – juanchopanza May 26 '18 at 16:44
  • 1
    @juanchopanza Yes, I meant it should not affect how you use the rule of three, five etc. – Killzone Kid May 26 '18 at 16:48
  • Possible duplicate of [Must a c++ interface obey the rule of five?](https://stackoverflow.com/q/49961811/2311167). However this question does not have an answer yet. Also possible duplicate of [Abstract class, copy constructor](https://stackoverflow.com/q/5593168/2311167) as the former rule of three has become the rule of five in C++11. – Adrian W May 26 '18 at 16:53
  • 1
    in this case `Rule of zero` should be respected. – Marek R May 26 '18 at 17:06
  • @MarekR So in order to respect the rule of zero but still keep a virtual destructor I'd need to either default or delete all the missing constructors/operators? I saw something along those lines in [CppCoreGuidelines](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#example-good-5) but I was wondering whether this also applies (and what use it has) if the base class has a pure virtual member function. – Markus Rothe May 26 '18 at 17:58

2 Answers2

1

"abstract" is irrelevant here. A class needs its own copy constructor, copy assignment operator, etc. if it has data that won't be properly copied by the default versions. Full stop. The presence or absence of pure virtual functions does not change this. Your example doesn't have any data, so doesn't have an issue here.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
  • It would make sense to make copy-assignment protected though. That way, anybody trying to do the assignment will be stopped. – Deduplicator May 26 '18 at 18:35
  • 2
    @Deduplicator — there are many things that may or may not be important depending on the **role** that a class is **designed** to fill. Being abstract is not a role; it is a tool, and its use does not in any way suggest limits on copying. – Pete Becker May 26 '18 at 21:04
0

Actually it is the contrary. I would consider deleting copying and assignment of a class that is supposed to be only an interface class to avoid slicing. Consider

class Base {
public:
    virtual ~Base() {}
};

class D1 : public Base {
    int i;
public:
    ~D1() override {}
};

class D2 : public Base {
    int i;
    double d;
public:
    ~D2() override {}
};

you could write something like this

vector<Base> vec;
D1 d;
  D2 e;
  vec.push_back(d);
  vec.push_back(e);

. You would try to squeeze an object of size D2 into a much smaller object of type base. By deleting copy and assignment you do prevent the user or yourself doing that.