I have a base class Base
and a derived class D
, and I'd like to have move constructor and move assignment operator automatically generated by the compiler for me. Following the Rule of Zero, I leave all memory management to the compiler and only use level-2 classes (no raw pointers, arrays, etc.):
#include <iostream>
class Base{
public:
Base(): a_(42) {}
virtual void show() { std::cout << "Base " << a_ << std::endl; }
private:
int a_;
};
class D : Base {
public:
D(): b_(666) {}
void show() { std::cout << "D " << b_ << std::endl; }
private:
int b_;
};
int main() {
Base b;
b.show();
D d;
d.show();
return 0;
}
This should be it, right?
Enter the C++ core guidelines:
A base class destructor should be either public and virtual, or protected and nonvirtual.
Ah, so I guess I'll have to add a destructor to Base
. But that'll do away with the automatically generated move functions!
What's the clean way out here?
You can = default
everything that you would like to be generated by the compiler.
See (at the bottom): http://en.cppreference.com/w/cpp/language/rule_of_three
In your case it could look something like:
class Base{
public:
Base(): a_(42) {}
Base(const Base&) = default;
Base(Base&&) = default;
Base& operator=(const Base&) = default;
Base& operator=(Base&&) = default;
virtual ~Base() = default;
virtual void show() { std::cout << "Base " << a_ << std::endl; }
private:
int a_;
};
You can create once a class like
struct VirtualBase
{
virtual ~VirtualBase() = default;
VirtualBase() = default;
VirtualBase(const VirtualBase&) = default;
VirtualBase(VirtualBase&&) = default;
VirtualBase& operator = (const VirtualBase&) = default;
VirtualBase& operator = (VirtualBase&&) = default;
};
And then follow rule of zero:
class Base : VirtualBase
{
public:
Base(): a_(42) {}
virtual void show() { std::cout << "Base " << a_ << std::endl; }
private:
int a_;
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With