There is no explicit destructor in base class. Then, I delete the derived class with derived pointer. After that, if I access the member of the derived class, the crash happened. However, if I access the base member, the program still ok. Why?
class Base {
public:
virtual void doSomething() = 0;
protected:
virtual ~Base() {} // if I remove the destructor, then the program still run ok even if I remove the derived class.
};
class Derived: public Base {
public:
Derived() {}
~Derived() {}
void doSomething() override { a_ = true; }
private:
bool a_;
};
Derived *pD = new Derived();
Base *pB = static_cast<Base*>(pD);
delete pD;
pB->doSomething(); // the program is ok if I remove the destructor in base class
pD->doSomething(); // the program crash no matter the destructor of base class is there or not.
if I access the member of derived class, the crash happpend.
if I access the base member, the program still ok. Why?
Because the behaviour of accessing through an invalid pointer is undefined.
Related
Example:
class Base {
public:
virtual void f() = 0;
virtual ~Base() { std::cout << "Base::~Base()\n"; }
};
class Derived : public Base {
public:
void f() { }
~Derived() { std::cout << "Derived::~Derived()\n"; }
};
int main() {
Base* p = new Derived();
delete p;
return 0;
}
Output:
Derived::~Derived()
Base::~Base()
I thought only the derived class destructor will be called since the pointed object to be freed is an instance of the derived class.
I have two questions:
Why was the virtual base destructor called?
Is it legally possible (or should it even be possible) to prevent the base class destructor from being called?
Why was the virtual base destructor called?
Because base class should be properly destructed. Derived class can not possibly do this.
Is it legally possible (or should it even be possible) to prevent the
base class destructor from being called?
No, because it would prevent properly destructing the base class (i.e. call it's members destructors)
I am learning C++ virtual functions.
#include<iostream>
class Base{
virtual void fun(){
std::cout<<"Base\n";
}
};
class Derived:public Base{
void fun(){
std::cout<<"Derived\n";
}
virtual void fun1(){
std::cout<<"Derived 1 \n";
}
};
int main(){
Base* b=new Derived();
b->fun1();
}
I wrote this piece of code but it is not compiling. As per the concept of dynamic polymorphism, if we create a pointer of base class pointing to derived class, then we can call the functions of derived class, right?. Using virtual pointer of class Derived, we can call the fun1 function in virtual table, right?
But why it is not compiling here?
You can't call any Base or Derived member functions from outside the classes since the functions are private. You need to make them public
The other problem:
fun1 is not a member of Base so you can't call fun1 via a base class pointer.
Two possible solutions:
Declare a pure virtual void fun1() = 0 in Base. Demo
Cast b to a Derived* before calling: static_cast<Derived*>(b)->fun1();. Demo
Your program is also leaking memory. You need to delete b; and when you do it would now call the Base destructor only (with undefined behavior as a result) since your Base doesn't have a virtual destructor.
virtual ~Base() = default;
And then in main:
// ...
delete b;
Demo using the smart pointer std::unique_ptr<Base> instead of having to delete manually.
When I am trying to delete the derived object polymorphically (that is: base class has public virtual destructor) why derived class private destructor is still being called? Why the scope resolution private is not working here.
class Base
{
protected:
Base() { cout << "Base constructor.\n"; }
public:
virtual ~Base() { cout << "Base destructor.\n"; }
};
class Derived :public Base
{
public:
Derived() { cout << "Derived constructor.\n"; }
private:
~Derived() { cout << "Derived destructor.\n"; }
};
int main()
{
Base *p = new Derived();
delete p;
}
Output:
Base constructor.
Derived constructor.
Derived destructor.
Base destructor.
Because destructors are called in reversed order of constructors and virtual destructor will always be called.
private has nothing to do if a virtual function is going to be called.
As I pointed here out:
Why would a virtual function be private?
ISO C++ 1998 Standard onwards explicitly states:
§10.3 [...] Access control (clause 11) is not considered in determining overriding.
A bit philosophical offtopic:
Going further this is what STL does for iostreams: Definition of Non-Virtual Interface, i.e. all public functions (with exception of destructors) are non-virtual and all virtual functions are either protected or private. Public functions call virtual protected or private ones. This gives a very clear entry point into the entire hierarchy.
It is, but you're not calling ~Derived() directly. If you were to use
Derived *p = new Derived();
delete p;
then you'd get the error. But when you access ~Derived() indirectly via polymorphism (e.g. by calling ~Base()), then the access specifier private does not apply.
According to [class.access.virt#1]:
The access rules (Clause [class.access]) for a virtual function are determined by its declaration and are not affected by the rules for a function that later overrides it. [ Example:
class B {
public:
virtual int f();
};
class D : public B {
private:
int f();
};
void f() {
D d;
B* pb = &d;
D* pd = &d;
pb->f(); // OK: B::f() is public, D::f() is invoked
pd->f(); // error: D::f() is private
}
— end example ]
And again in footnote 111 in [class.virtual]:
Access control is not considered in determining overriding.
You use a virtual destructor because you want all the destructor in your inheritance to get called. That exactly what you get. The private does not apply as you don't call the destructor explicitly.
If your destructor was not virtual you will get only Base::~Base() called. Usually that's not what you want when you have polymorphism.
You can call the destructor through a pointer to B, because it's already public there. It's the static type of the pointer which is used to determine that access in this case.
[class.access.virt/1]
The access rules (Clause [class.access]) for a virtual function are
determined by its declaration and are not affected by the rules for a
function that later overrides it. [ Example:
class B {
public:
virtual int f();
};
class D : public B {
private:
int f();
};
void f() {
D d;
B* pb = &d;
D* pd = &d;
pb->f(); // OK: B::f() is public, D::f() is invoked
pd->f(); // error: D::f() is private
}
— end example ]
This keeps virtual functions in line with the Liskov Substitution Principle
You delete the derived class through the base class pointer. With the help of the virtual destructor you start the delete at the derived class. Because that class can access its private members, it call the private destructor. After that the base class is calling the public destructor.
Note that you call delete and not calling de destructor Derived::~Derived() direct!
I have following
class base
{
};
class derived : public base
{
public:
derived() {}
void myFunc() { cout << "My derived function" << std::endl; }
};
now I have
base* pbase = new derived();
pbase->myFunc();
I am getting error myFunc is not a member function of base.
How to avoid this? and how to make myFunc get called?
Note I should have base class contain no function as it is part of design and above code is part of big function
If you are adamant that this function should NOT be a part of base, you have but 2 options to do it.
Either use a pointer to derived class
derived* pDerived = new derived();
pDerived->myFunc();
Or (uglier & vehemently discouraged) static_cast the pointer up to derived class type and then call the function
NOTE: To be used with caution. Only use when you are SURE of the type of the pointer you are casting, i.e. you are sure that pbase is a derived or a type derived from derived. In this particular case its ok, but im guessing this is only an example of the actual code.
base* pbase = new derived();
static_cast<derived*>(pbase)->myFunc();
myfunc needs to be accessible from the base class, so you would have to declare a public virtual myfunc in base. You could make it pure virtual if you intend for base to be an abstract base class, i.e one that cannot be instantiated and acts as an interface:
class base
{
public:
virtual void myfunc() = 0; // pure virtual method
};
If you ant to be able to instantiate base objects then you would have to provide an implementation for myfunc:
class base
{
public:
virtual void myfunc() {}; // virtual method with empty implementation
};
There is no other clean way to do this if you want to access the function from a pointer to a base class. The safetest option is to use a dynamic_cast
base* pbase = new derived;
....
derived* pderived = dynamic_cast<derived*>(pbase);
if (derived) {
// do something
} else {
// error
}
To use the base class pointer, you must change the base class definition to be:
class base
{
public:
virtual void myFunc() { }
};
I see no other way around it. Sorry.
You could add it as a member of base and make it a virtual or pure virtual function. If using this route however, you should also add a virtual destructor in the base class to allow successful destruction of inherited objects.
class base
{
public:
virtual ~base(){};
virtual void myFunc() = 0;
};
class derived : public base
{
public:
derived() {}
void myFunc() { cout << "My derived function" << std::endl; }
};
I have two classes:
class A {
public:
virtual void somefunction() = 0;
};
class B : public A {
public:
B();
~B();
void somefunction();
};
B::B() {}
void B::somefunction() {
// some code
}
But with g++ I get errors:
class A has virtual functions and accessible non-virtual destructor
class B has virtual functions and accessible non-virtual destructor
I don't have any idea what this error is... Somewhere on blogs I read that it's a compiler warning. How can I fix the problem?
This happens because your base class A does not have a virtual destructor. For instance, if you had this code:
int main()
{
A* a = new B;
delete a;
}
Then the delete a call would not be able to call B's destructor because A's isn't virtual. (It would leak all of B's resources.) You can read more about virtual destructors here.
Add a virtual destructor to your base class and you should be fine.
class A
{
public:
virtual void somefunction() = 0;
virtual ~A() = default;
}
Give class A:
virtual ~A() { }
That way, derived classes such as B will still have their custom destructor called if you delete them via an A*.
As thumb rule(IMHO) or in Short the destructor in the base class has to be either public and virtual or protected non virtual to prevent the memory leaks.by doing so the destructors of the derived class get called and this prevents the memory leakage whenever the Base pointer/reference holding derived address/reference is deleted.
If a class has virtual functions then its destructor should be virtual as well. Yours has an accessible destructor but it is not virtual.