Am I correct?
Yes, as per ForEveR's post.
Is there any way to avoid that?
Yes. Do this just once by implementing a base for all polymorphic classes (similarly to class Object
in Java and D which is the root of all class hierarchies):
struct polymorphic {
polymorphic() = default;
virtual ~polymorphic() = default;
polymorphic(const polymorphic&) = default;
polymorphic& operator =(const polymorphic&) = default;
// Those are not required but they don't harm and are nice for documentation
polymorphic(polymorphic&&) = default;
polymorphic& operator =(polymorphic&&) = default;
};
Then, any class publicly derived from polymorphic
will have a implicitly declared and defined (as defaulted) virtual destructor unless you declare one yourself.
class my_polymorphic_class : public polymorphic {
};
static_assert(std::is_default_constructible<my_polymorphic_class>::value, "");
static_assert(std::is_copy_constructible <my_polymorphic_class>::value, "");
static_assert(std::is_copy_assignable <my_polymorphic_class>::value, "");
static_assert(std::is_move_constructible <my_polymorphic_class>::value, "");
static_assert(std::is_move_assignable <my_polymorphic_class>::value, "");
What is the logic behind this?
I can't be sure. What follows are just speculations.
In C++98/03, the Rule of Three says that if a class needs either the copy constructor, the copy assignment operator or the destructor to be user defined, then it probably needs the three to be user defined.
Obeying the Rule of Three is a good practice but this is nothing more than a guideline. The Standard doens't force it. Why not? My guess is that people realized this rule only after the publication of the Standard.
C++11 introduced move constructor and move assignment operator, turning the Rule of Three into the Rule of Five. With benefit of hindsight, the committee wanted to enforce the Rule of Five. The idea was: if either of the five special functions is user declared then the others, but the destructor, won't be implicitly defaulted.
However, the committee didn't want to break virtually every C++98/03 code by enforcing this rule and then, decided to do it only partially:
If either the move constructor or the move assignment operator is user declared then other special functions, but the destructor, will be deleted.
If either of the five special functions is user declared then the move constructor and move assignment operators won't be implicitly declared.
In the case of C++98/03 well formed code, neither a move constructor nor a move assignment operator is ever user declared then, rule 1 doesn't apply. Hence when compiled with a C++11 compliant compiler C++98/03 well formed code doesn't fail to compile as a consequence of this rule. (If it does, it's for some other reasons.)
In addition, under rule 2 the move constructor and move assignment operator are not implicitly declared. This doesn't break C++98/03 well formed code either because they never expected the declaration of move operations anyway.
The deprecation mentioned in the OP and quoted in ForEveR's post suggests a possible enforcement of the Rule of Five by a future Standard. Be prepared!