coder777 wrote: |
---|
Is there a point for using = default for the destructor? |
We must mention the destructor because the implicit one would be non-virtual. If the base-class destructor was non-virtual, it would be undefined behavior to
delete derived class objects through a pointer to base.
https://stackoverflow.com/questions/461203/when-to-use-virtual-destructors
As opposed to an empty definition (
virtual ~ A() {}), the distinction is that the empty-braces makes a
user-provided destructor, and in that case the implicit generation of defaulted
copy constructors and
copy assignment operators is deprecated. For example, experimental GCC 9 emits a warning if you put braces and try to copy:
https://godbolt.org/z/C4aSno .
This works with the
Rule of Three: if one has a class that needs a user-provided destructor, then that class probably needs a user-provided copy-constructor & copy assignment operator, or else shouldn't be copyable at all.
The consequence is simple: if a class is not managing resources and is therefore conforming to the
Rule of Zero, then either don't mention the destructor at all (if possible) or explicitly default it
on its first declaration otherwise - don't write empty braces.
Further, to the programmer, the intent is clearer.
https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rc-eqdefault
This wording is in the current working draft:
http://eel.is/c++draft/depr.impldec#1
wengwengweng wrote: |
---|
What about class C has a member function void log2() that class A doesn't have and I want to call it from a A* collection, how can I do it? |
Maybe the right cast there is
dynamic_cast? (Unless you're
certain that you'll never pick the wrong type.)
In any event:
If adding a base-class method doesn't make sense for all derived classes, then your class hierarchy violates the Liskov Substitution Principle. The best solution is probably to refactor the design. Maybe your objects should
have sprites instead of
be sprites?
https://en.wikipedia.org/wiki/Liskov_substitution_principle
If you are using a class hierarchy to approximate a discriminated union, use a discriminated union directly. The standard one is called
std::variant, but you could also reach for the boost libraries (
boost::variant) if you don't have the luxury of a new compiler.
The right answer depends on circumstances. What are you trying to do?