Inheritance from std::enable_shared_from_this - c++

I have next code:
class A
{
virtual ~A() = default;
virtual void foo1() = 0;
};
class B
{
virtual ~B() = default;
virtual void foo2() = 0;
};
class C: public A, public std::enable_shared_from_this<C>, public B
{
void foo1() override
{
}
void foo2() override
{
}
};
Is it correct that class std::enable_shared_from_this goes before class B? Does it matter where std::enable_shared_from_this is?

Does it matter where std::enable_shared_from_this is?
Technically it doesn't matter.
The order of derivation affects the order of constructor and destructor invocation.
From a construction perspective, enable_shared_from_this<T> constructor is a no-op; it simply adds a value-initialized, i.e. empty, weak_ptr-to-self to the class, and is detected by shared_ptr<T> constructor, which assigns itself to that member right after the object is fully constructed.
From a destruction perspective it also doesn't matter even if a destructor of another base before or after it throws. The destructor will still be invoked and the weak counter of the corresponding shared_ptr, if any, will be properly decremented, allowing it to be freed when the time comes (for the really curious, the exception cleanup rules can be found here).
It might matter from a code style perspective, however. For example, the following declaration is arguably more readable:
class C: public A, public B, public std::enable_shared_from_this<C>
. . .

It does not matter.
The order of base classes may affect:
Construction order (first base first, except for virtual inheritance)
Memory layout order (not deterministic, may not affect)
So, only construction order matters.
But you cannot use shared_from_this in a base class constructor/destructor anyway.
You cannot use it even in body of constructor or destructor of current class, as it will throw exception until it is placed inside shared_ptr<C>, or shared_ptr<D>, whatever. And you don't even have an easy way to attempt shared_from_this from base class, as you cannot call virtual functions from constructor of base class the way that the derived implementation is called.
So it does not matter at all.

Related

Must I either mark the destructor of the base class as virtual function or mark it as protected function?

As per this article, which says that[emphasis mine]:
Making base class destructor virtual guarantees that the object of derived class is destructed properly, i.e., both base class and derived class destructors are called.
As a guideline, any time you have a virtual function in a class, you should immediately add a virtual destructor (even if it does nothing). This way, you ensure against any surprises later.
I think even if your base class has no virtual function,you should either add a virtual destructor or mark the destructor of the base class as protected.Otherwise, you may face memory leak when trying to delete a pointer pointed to a derived instance. Am I right?
For example,here is the demo code snippet:
#include<iostream>
class Base {
public:
Base(){};
~Base(){std::cout << "~Base()" << std::endl;};
};
class Derived : public Base {
private:
double val;
public:
Derived(const double& _val){};
~Derived(){std::cout << "~Derived()" << std::endl;}; //It would not be called
};
void do_something() {
Base* p = new Derived{1};
delete p;
}
int main()
{
do_something();
}
Here is the output of the said code snippet:
~Base()
Could anybody shed some light on this matter?
The behavior of the program in the question is undefined. It deletes an object of a derived type through a pointer to its base type and the base type does not have a virtual destructor. So don't do that.
Some people like to write code that has extra overhead in order to "ensure against any surprises later". I prefer to write code that does what I need and to document what it does. If I decide later that I need it to do more, I can change it.
This question will lead to a bunch of other questions about whether a programmer should always be super safe by protecting its code even against currently non existent problems.
In your current code, the Derived class only adds a trivial double to its base class, and a rather useless destructor, that only contains a trace print. If you deleted an object through a pointer to the base class, the Derived destructor will not be called, but it will be harmless. Furthermore, as you were told in the comment, using polymorphism (casting a pointer to a base class one) with no virtual function does not really makes sense.
Long story made short, if you have a class hierarchy with no virtual function, users are aware of it and never delete an object through a pointer to its base class. So you have no strong reason to make the destructor virtual nor protected. But IMHO, you should at least leave a comment on the base class to warn future maintainers about that possible problem.
Without a virtual destructor your call to delete is arguably wrong. It should be:
void do_something() {
Base* p = new Derived{1};
Derived *t = dynamic_cast<Derived*>(p);
if (t) {
delete t;
} else {
delete p;
}
}
You can use up/down casting of objects to store them in a common array or vector and still be able to call methods of the derived objects all without a virtual destructor. It's usually a sign of bad design but it is legal C++ code. The cost is that you have to do cast back to the original types before delete like above.
Note: The dynamic_cast can only be done when Base has at least one virtual function. And if you have a virtual functions you should just add the virtual destructor.
And if you don't need to dynmaic_cast anywhere then show me case where you can't use an array of Base instead of Base *.
The point of making the destructor of the base class protected I guess is to generate an error when someone deletes a Base* so you can then make the destructor virtual. Means you don't have the overhead of a virtual destructor until you actually need it.
fwiw it's happening because you try to delete it through Base. if you somehow really want to have object reference/pointer of only the base type, there are some alternatives.
void do_something() {
Base&& b = Derived{1};
}
void do_something() {
Derived d{1};
Base* p = &d;
Base& b = d;
}
void do_something() {
std::shared_ptr<Base> sb = std::make_shared<Derived>(1);
}
// NOTE: `std::unique_ptr` doesn't work
void do_something() {
std::unique_ptr<Base> ub = std::make_unique<Derived>(1); // warning: this not work
}

Does C++ create default "Constructor/Destructor/Copy Constructor/Copy assignment operator" for pure virtual class?

Do C++ compilers generate the default functions like Constructor/Destructor/Copy-Constructor... for this "class"?
class IMyInterface
{
virtual void MyInterfaceFunction() = 0;
}
I mean it is not possible to instantiate this "class", so i think no default functions are generated.
Otherwise, people are saying you have to use a virtual destructor.
Which means if i dont define the destructor virtual it will be default created, not virtual.
Furthermore i wannt to know if it is reasonable to define a virtual destructor for a pure virtual Interface, like the one above? (So no pointers or data is used in here, so nothing has to be destructed)
Thanks.
Yes.
There is no wording that requires the class to be instantiable in order for these special member functions to be implicitly declared.
This makes sense — just because you cannot instantiate the Base, doesn't mean a Derived class doesn't want to use these functions.
struct Base
{
virtual void foo() = 0;
int x;
};
struct Derived : Base
{
Derived() {}; // needs access to Base's trivial implicit ctor
virtual void foo() {}
};
See:
§12.1/5 (ctor)
§12.8/9 (move)
§12.8/20 (copy)
Furthermore i wannt to know if it is reasonable to define a virtual destructor for a pure virtual Interface, like the one above? (So no pointers or data is used in here, so nothing has to be destructed)
It's not only reasonable, it's recommended. This is because in the case of virtual function hierarchies, (automatically) calling a destructor of a specialized class also calls all destructors of it's base classes. If they are not defined, you should get a linking error.
If you define at least one virtual function in your class you should also define a virtual destructor.
The destructor can be defined with =default though:
Here's a corrected (compilable) code example:
class ImyInterface
{
virtual void myInterfaceFunction() = 0;
virtual ~ImyInterface() = 0;
}
ImyInterface::~ImyInterface() = default;
Furthermore i wannt to know if it is reasonable to define a virtual destructor for a pure virtual Interface, like the one above? (So no pointers or data is used in here, so nothing has to be destructed)
Will the derived classes ever do anything in their destructors? Can you be certain they never will, even when somebody else takes over development?
The whole point of having a virtual destructor is not to make sure the base class is properly destructed, that will happen anyway. The point is that the derived class's destructor is called when you use a generic interface:
struct A {
virtual ~A() {}
virtual int f() = 0;
};
class B : public A {
std::ifstream fh;
public:
virtual ~B() {}
virtual int f() { return 42; }
};
std::shared_ptr<A> a = new B;
When a goes out of scope, why is the ifstream closed? Because the destructor deletes the object using the virtual destructor.
This addresses the second question about declaring a virtual destructor for an abstract base class (e.g. at least one member function is pure virtual). Here is a real world example of the LLVM clang++ compiler catching a potential problem. This occurred with the command line tools version supplied by Apple Developer for the Mac OS X Mavericks operating system.
Suppose you have a collection of derived classes that ultimately have the parent with the abstract base class to define the common interface. Then it is necessary to have a storage container like a vector that is intentionally declared to store a pointer to the abstract base class for each element. Later on, following good engineering practices, the container elements need to be "deleted" and the memory returned to the heap. The simplest way to do this is to traverse the vector element by element and invoke the delete operation on each one.
Well, if the abstract base class does not declare the destructor as virtual, the clang++ compiler gives a friendly warning about calling the non-virtual destructor on an abstract class. Keep in mind that in reality only the derived classes are allocated from the heap with operator new. The derived class pointer type from the inheritance relationship is indeed the abstract base class type (e.g. the is-a relationship).
If the abstract base class destructor is not virtual, then how will the correct derived class' destructor be invoked to release the memory? At best the compiler knows better (at least potentially does with C++11), and makes it happen. If the -Wall compiler option is enabled, then at least the compilation warning should appear. However, at worse, the derived class destructor is never reached and the memory is never returned to the heap. Hence there is now a memory leak that may be very challenging to track down and fix. All it will take is a single addition of "virtual" to the abstract base class destructor declaration.
Example code:
class abstractBase
{
public:
abstractBase() { };
~abstractBase() { };
virtual int foo() = 0;
};
class derived : abstractBase
{
public:
derived() { };
~derived() { };
int foo() override { return 42; }
};
//
// Later on, within a file like main.cpp . . .
// (header file includes are assumed to be satisfied)
//
vector<abstractBase*> v;
for (auto i = 0; i < 1000; i++)
{
v.push_back(new derived());
}
//
// do other stuff, logic, what not
//
//
// heap is running low, release memory from vector v above
//
for (auto i = v.begin(); i < v.end(); i++)
{
delete (*i); // problem is right here, how to find the derived class' destructor?
}
To resolve this potential memory leak, the abstract base class has to declare its destructor as virtual. Nothing else is required. The abstract base class now becomes:
class abstractBase
{
public:
abstractBase() { };
virtual ~abstractBase() { }; // insert virtual right here
virtual int foo() = 0;
}
Note that the abstract base class has currently empty constructor and destructor bodies. As Lightness answered above, the compiler creates a default constructor, destructor, and copy constructor for an abstract base class (if not defined by the engineer). It is highly recommended to review any of The C++ Programming Language editions by the C++ creator, Bjarne Stroustrup, for more details on abstract base classes.

Override Destructor C++

From the C++ FAQ:
[11.4] Can I overload the destructor for my class?
No.
I realize this means you cannot change the return type, arguments' types nor the number of arguments. I may be splitting hairs on the syntax of the words, but is it possible to override the Parent's destructor?
class Child : public Parent {
public:
virtual Parent::~Parent() {
// New definition
}
};
And for that matter do it recursively?
class Grandchild : public Child {
public:
Child::Parent::~Parent() {
// An even newer definition
}
};
I've read this and a related post and it makes me think because destructors are not inherited, they cannot be overridden, but I've never seen it explicitly stated.
EDIT: I changed this to reflect the fact that I want to override the Parent's destructor, note Child and Grandchild overriding ~Parent().
The main reason I am doing this is to maintain Parent's interface while changing the way it is destroyed (the entire reason for the child class). I will have something else managing all Parent's created and will explicitly call their destructors at a later time of my choosing.
I may be splitting hairs on the syntax of the words
No, you are definitely not – these are two very different things.
but is it possible to override the destructor?
Yes, and in fact you must do this in many cases. In order for this to work for a polymorphic object, you need to declare the base class destructor as virtual, though:
Parent const& p = Child();
Will properly call p.~Child() at the end of scope because Parent::~Parent is virtual.
Yes, it is possible to override the destructor of a class. In fact, when you define a class hierarchy in which polymorphism is used, you must declare a virtual destructor in the base class.
Overrides of destructors work exactly the same way overrides of normal member functions work in that when you destroy an object by deleteing the object via a pointer to the base class, the destructor of the derived class is properly called. This is why you must have a virtual destructor in the base class for polymorphic hierarchies.
However, there is a difference between virtual destructors and virtual member methods which has nothing to do with the virtual nature of the destructor. That is, when executing code like this:
class A
{
public:
virtual void Foo() {}
virtual ~A() {};
};
class B : public A
{
public:
void Foo() {};
~B() {}
};
int main()
{
A* a = new B;
a->Foo(); // B::Foo() is called
delete a; // B is destroyed via B::~B()
}
...when you call a->Foo(), the method Foo() in B is called. Since B::Foo() doesn't explicitly call A::Foo(), A::Foo() isn't called.
However, when the object is destroyed via delete a;, first the destructor B::~B() is called, and then after that finishes but before control returns to the program, the base class destructor A::~A() is also called.
Of course this is obvious when you think about it, and again this has nothing to do with the virtual nature of the destructor, but it does behave differently than a normal virtual method call, so I thought I'd point it out.
Obligitory Standard Quotation:
[C++03] 12.4/6 : Destructors
After executing the body of the destructor and destroying any
automatic objects allocated within the body, a destructor for class X
calls the destructors for X’s direct members, the destructors for X’s
direct base classes and, if X is the type of the most derived class
(12.6.2), its destructor calls the destructors for X’s virtual base
classes. All destructors are called as if they were referenced with a qualified name, that is, ignoring any possible virtual
overriding destructors in more derived classes. Bases and members are
destroyed in the reverse order of the completion of their
constructor (see 12.6.2). A return statement (6.6.3) in a destructor
might not directly return to the caller; before transferring control
to the caller, the destructors for the members and bases are called.
Destructors for elements of an array are called in reverse order of
their construction (see 12.6).
Yes: you can have virtual destructors, and the only reason is to override them in derived classes.
It looks like this:
class Parent {
public:
virtual ~Parent();
};
class Child : public Parent {
public:
virtual ~Child();
};
class Grandchild : public Child {
public:
~Grandchild(); // virtual is inherited here
};
Note that the destructor isn't overridden by name like ordinary functions, because the name is always that of the class whose instance you're destroying.
Note also that the parent class' destructors are always called too, so you don't need to duplicate their cleanup code: read up on member object and base-class sub-object construction and destruction order for the details.
Terminology
overriding a function means implementing a base-class virtual function in a derived class. You can't change the signature at all (except for using covariant return types). So, an override always has the same signature as an inherited virtual function.
overloading a function means implementing multiple functions with the same name (and in some sense the same scope). So, an overload always has a different signature to the others with the same name, doesn't relate directly to virtual dispatch, and isn't necessarily inherited.
Yes; you can, and should, make a destructor virtual, whenever you have a child class which may be destroyed using a reference to the base class. Static code analysis tools will even complain if you don't offer a virtual destructor.
Consider the following example:
class A
{
public:
A() { a = new int; }
virtual ~A() { delete a; }
private:
int *a;
};
class B final : public A
{
public:
B() { b = new int; }
~B() { delete b; }
private:
int *b;
};
int main()
{
A *a = new B();
delete a;
}
If A's destructor was not virtual, then delete a would only call A's destructor, and you would end up with a memory leak. But because it's virtual, both destructors will be called, in the order ~B() -> ~A().

When and why should destructor in base class NOT be defined as virtual?

This example below illustrates how to prevent derived class from being copied. It's based on a base class where both the copy constructor and copy assignment operator are declared private.
class Uncopyable
{
protected:
// allow construction and destruction of derived objects...
Uncopyable() {}
~Uncopyable() {}
private:
// but prevent copying...
Uncopyable(const Uncopyable&);
Uncopyable& operator=(const Uncopyable&);
};
We can use this class, combined with private inheritance, to make classes uncopyable:
class derived: private Uncopyable
{...};
Notice that the destructor in class Uncopyable is not declared as virtual.
Previously, I learned that
Destructors in base classes should be virtual.
Destructors in non-base classes should not be made virtual.
In this example, the destructor for Uncopyable is not virtual, but it is being inherited from. This seems to go against the wisdom I've learned previously.
When and why should destructor in base class NOT be defined as virtual?
A base class destructor only needs to be virtual if you might try deallocating an object of a derived type through a pointer of the base type. Consequently, if you only inherit from the base class privately instead of publicly, as would be the case in Uncopyable, then you don't need to worry about putting in a virtual destructor, because when using private inheritance you can't get a pointer to the derived object and store it in a pointer to the base type.
Another example might be if you were to use a mixin class like this one that makes a class track the number of object allocations, where the mixin is inherited from to acquire behavior but not to be treated polymorphically:
template <typename T> class Counter {
public:
Counter() { ++numInstances; }
Counter(const Counter&) { ++numInstances );
~Counter() { --numInstances; }
static unsigned getNumInstances() { return numInstances; }
private:
static unsigned numInstances;
}
template <typename T> unsigned Counter<T>::numInstances = 0;
More generally, when using static polymorphism, you don't need virtual destructors because you never treat the classes polymorphically using pointers to the base type. You only use a pointer to the derived type.
There are probably a few other cases I didn't cover here, but these two (private inheritance, mixin classes, and static polymorphism) cover much of the space where virtual destructors aren't required.
When you design the base not as interface, but as implementation detail (note the private inheritance from Uncopyable).
You technically don't have to make your decostructor virtual if you know nobody will delete it as a Uncopyable*, but will always delete it as a subclass of the same.
Yes this is essentially, what #templatetypedef said, but I'm going to explain it in a maybe easier way.
So: if people might do something like this:
void aFunction(Uncopyable* obj) {
delete obj;
}
Then you should declare your destructor virtual (to make sure potential subclasses get their destructor called.
However, if you know people will be deleting Subclasses like so:
class Widget : public Uncopyable
{
....
};
void aFunction(Widget* obj) {
delete obj;
}
Then you don't have to make your destructor virtual (as the subclasses destructor will be called).
At least, that's my understanding.
When you need your objects to be plain old data, with no vtable. I'd comment the heck out of it if I ever needed it, as 99% of the time leaving off the 'virtual' in base class destructors is simply a mistake that someone will want to correct.
The general rule is to make your destructor public and virtual, or protected and non-virtual. In the first case, your object use destroyable polymorphically and teh virtual destructor will do the right thing. In the second case it will only be destroyed as the actual child class and still do the right thing.

Virtual destructors for interfaces

Do interfaces need a virtual destructor, or is the auto-generated one fine? For example, which of the following two code snippets is best, and why? Please note that these are the WHOLE class. There are no other methods, variables, etc. In Java-speak, this is an "interface".
class Base
{
public:
virtual void foo() = 0;
virtual ~Base() {}
};
OR...
class Base
{
public:
virtual void foo() = 0;
~Base() {} // This line can be omitted, but included for clarity.
};
EDIT DUE TO "NOT WHAT I'M LOOKING FOR" ANSWERS:
Exactly what are the consequences of each route. Please don't give vague answers like "it won't be destructed properly". Please tell me exactly what will happen. I'm a bit of an assembly nerd.
Edit 2:
I am well aware that the "virtual" tag means that the destructor won't get called if deleted through a pointer to derived, but (I think) this question ultimately boils down to "is it safe to omit that destructor, for is it truly trivial?"
EDIT 3:
My second edit is just plain wrong and disinformation. Please read the comments by actual smart people for more info.
Consider the following case:
Base *Var = new Derived();
delete Var;
You need the virtual destructor, otherwise when you delete Var, the derived class' destructor will never be called.
If you delete a derived class object via a base class pointer in C++, the result is undefined behaviour. UB is something you really want to avoid, so you must give base classes a virtual destructor. To quote from the C++ Standard, section 5.3.5:
if the static type of the operand is
different from its dynamic type, the
static type shall be a base class of
the operand’s dynamic type and the
static type shall have a virtual
destructor or the behavior is
undefined.
You should use a virtual destructor if you expect people to try to delete objects of a derived class via pointers or references of the parent class. If this is the case, then without a virtual destructor, the derived class will never be properly destructed.
For example,
Derived::~Derived() { // important stuff }
Base *foo = new Derived();
delete foo;
Without a virtual destructor in Base, Derived's destructor will never be called, and important stuff will therefore never happen.
Replying mostly to the edit:
Nobody can tell you what will happen because the result is "undefined behavior". When you delete a derived class through a pointer to a base that has no virtual destructor, the implementation is free to break down in any number of ways.
In general, a destructor should be either (1) public and virtual, or (2) protected and non-virtual.
Assuming you never expect anyone to delete a class instance via an interface pointer, a protected non-virtual destructor is 100% safe.
If someone tries to delete an interface pointer in case (2), they'll get a compile-time error.
No... virtual destructors are not auto generated. You have to declare them explicitely in your base class.
But you won't need to declare your destructors virtual for the child classes of Base. This is done by the compiler.
The compiler will also make sure that the destructors are called in reversed order of construction (from derived to base).
public class Base
{
//...
}
public class Derived
{
int i = 0;
//...
}
//...
Base* b = new Derived();
If you didn't have a virtual destructor
delete b;
would cause memory leaks (at least 4 bytes for the integer field), because it would destruct only Base and not Derived. The virtuality makes sure that the derived classes are destroyed, too. You won't have to declare a virtual constructor in Derived, this will be inferred by the compiler, if you declared a virtual destructor in Base.