I'm newbie in C++. I'm learning c++ oops concepts. Is it allowed to using Derived class(D) allocate the memory of Base class(B) pointer?
B *a = new D();
My code:
#include <iostream>
using namespace std;
class B
{
public:
B()
{
cout<<"B constructor"<<endl;
}
~B()
{
cout<<"B Destroctur"<<endl;
}
};
class D : public B
{
public:
D()
{
cout<<"D constructor"<<endl;
}
~D()
{
cout<<"D Destroctur"<<endl;
}
};
int main()
{
B *a = new D();
delete a; // Is valid?
}
Also, Is it valid to free the memory of base class pointer?
delete a;
it is valid as long as you declare base destructor virtual:
virtual ~B() { /*B destructot code*/}
What you did was created and object of class D which is derived from class B. Pointer of type B that the address of created object is assigned to is a pointer with instruction to point to "B part of class D". The object created is still of class D and can be cast into class D pointer.
This is also a way to restrict usage of D class functionalities in a current scope or create a list of objects with different types which must all be derived from the same base class (typical example is dog and cat class extend animal class and are both put in pets<animal> list)
As per your code, the output will be
B constructor
D constructor
B Destructor ==> Base class
Derived class memory will not deleted. So avoid that, we need to use virtual keyword in base class destructor.
virtual ~B()
{
cout<<"B Destroctur"<<endl;
}
during run time, while calling base class (B) destructor, it calls derived class destructor (D) and then base class destructor executed.
if base class destructor is virtual, the output will be
B constructor
D constructor
D Destructor ==> Derived class
B Destructor ==> Base class
Related
From https://en.cppreference.com/w/cpp/language/dynamic_cast:
dynamic_cast < new_type > ( expression )
3) If new_type is a pointer or reference to Base, and the type of expression is a pointer or reference to Derived, where Base is a unique, accessible base class of Derived, the result is a pointer or reference to the Base class subobject within the Derived object pointed or identified by expression. (Note: an implicit conversion and static_cast can perform this conversion as well.)
Sample code:
#include <iostream>
using namespace std;
class A {
//public:
// virtual ~A() {
//
// }
};
class B : public A {
};
class C : public B {
};
class D : public B, public A {
};
int main()
{
D* pd = new D;
if (B* pa = dynamic_cast<B*>(pd)) {
cout << "1";
}
return 0;
}
No error or warning under VC++
warning: direct base 'A' inaccessible in 'D' due to ambiguity under gcc, link
Shouldn't I expect a compile error?
Now I find that if I try to convert D* to A*, a error would occur, but as mentioned above, from D* to B*, no error.
int main()
{
D* pd = new D;
if (A* pa = dynamic_cast<A*>(pd)) {
cout << "1";
}
return 0;
}
link
In that context, unique means that Derived contains new_type only once, not that Derived derives from a single base class.
So, in your example, B is unique, because D contains it only once.
In your example, D contains A twice (once directly, and once through B), so a cast to A cannot be made, as A is not unique.
Note, that "containment" what it counts. So, in this example, C derives from Base twice, yet it is fine, as Base is inherited with the keyword virtual:
struct Base { };
struct A: virtual Base { };
struct B: virtual Base { };
struct C: A, B { };
int main() {
C c;
dynamic_cast<Base &>(c);
}
(If I haven't used virtual, then Base would have been ambiguous)
Note: I'd use static_cast instead, as it can do the cast in this case as well. Using dynamic_cast is a little bit misleading here, as the cast will be done compile-time, and not run-time.
The warning causes by indirect base class issue in multiple-inheritance model. D has two copies of base class A, one directly and one indirectly via B. When a base class is specified as a virtual base (same as #geza example), there is only one copy of base class' data members shared between virtual base classes.
class A {
public:
A() {}
};
class B : virtual public A {
public:
B() : A() {}
};
class C : public B, virtual public A {
public:
C() : B() {}
};
int main()
{
A* pa = static_cast<A *>(new C()); // no more warning since A is virtual
return 0;
}
It's well explained here: Multiple Base Classes.
I am new to OO programming and I was wondering how to solve the following question -
I have the following:
class A
{
public:
A() {};
~A() {};
virtual functionA() = 0;
}
class B: public A
{
public:
B() {};
~B() {};
functionA();
functionB();
}
Is there a way to access functionB using an object of the base class A? If no, why is it not possible? If yes, how does one do it? I tried to find this answer on this site but I didn't find anything concrete.
I would modify your example slightly to give you a better understanding:
class Animal
{
public:
A() {};
~A() {};
virtual Eat() = 0;
}
class Bird: public Animal
{
public:
B() {};
~B() {};
Eat();
Fly();
}
Should an Animal object be allowed to access the function Fly which belongs to Bird ?
No, because not all Animals are Birds.
But if you are sure than a specific Animal object is a Bird, then you can downcast the Animal object to Bird and then call Fly function.
However, this is not generally recommended. Upcasts (casting Bird to Animal) are okay because all Birds are Animals.
In general this is not possible. Class A can't access derived methods in Class B. The general relationship is upward for inheritance. Imagine a Class C that also has functionB, the resolution would be ambiguous.
class A
{
}
class B:public A
{
void functionB() {};
}
class C:public A
{
void functionB() {}
}
main()
{
A a;
a.functionB(); // What to call here?
}
With that being said, if an instance is in fact a B then a downcast could be used.
main()
{
B b;
A&a = b; // ok since a B is-a A
auto & b1 = dynamic_cast<B&>(a); // ok since this particular instance is-a B
b1.functionB();
}
perhaps this is what you were reaching for.
You can access only virtual method of B using the object A. This is called runtime-polymorphism and it is achieved with virtual function. Hence in order to implement the runtime behaviour C++ compiler inserts Virtual Table for every class having virtual function or class inherited from the class that has virtual function.
As in your code, i will make small modification:-
class A
{
public:
A() {};
~A() {};
virtual void functionA() = 0;
virtual void functionC();
}
class B: public A
{
public:
B() {};
~B() {};
void functionA() override; // C++ 11 : override keyword ensures that the function is virtual and is overriding a virtual function from a base class.
void functionB();
}
As the class A contains a virtual function C++ compiler inserts a pointer v_ptr called as virtual table pointer. Compiler also creates a table for that class called as virtual table known as vtable for the class. The table is created compile time v_ptr holds the address of v_table of the corresponding class. vtable is a array of function pointers pointing to virtual function. As functionA is pure virtual so in vtable the address entry for functionA will be null and but functionC has a valid address entry in vtable as it is not pure virtual function.
virtual table contains pointers to functionA() and functionC function of A class. But the implementation is incomplete as functionA is pure virtual. So you can't create object of class A.
As B Class inherits from A class, and as we know A class has a data member v_ptr. B class inherits v_ptr of A class but new virtual table will be created compile time for B class. Hence v_ptr of B class holds the address of vtable of B class. As B class has implemented functionA function. vtable of B class contains pointer to functionA function of B class but pointer to functionC function of base class i.e A class.
A *a = new B();
a->functionA(); //calls B functionA
a->functionC(); //calls A functionC since we haven't overriden this function in B
I am trying to understand virtual destructors. The following is a copy paste from this page When to use virtual destructors?
Here, you'll notice that I didn't declare Base's destructor to be
virtual. Now, let's have a look at the following snippet:
Base *b = new Derived(); // use b
delete b; // Here's the problem!
[...] If you want to prevent the deletion of an instance through a base class pointer, you can make the base class destructor protected and non-virtual; by doing so, the compiler won't let you call delete on a base class pointer.
I don't understand why the deletion is prevented by having a protected non-virtual base class destructor. Doesn't the compiler think that we're trying to call delete from a base class object? What does protected have to do with that?
The C++ Standard has this to say about delete (section 5.3.5p10):
Access and ambiguity control are done for both the deallocation function and the destructor (12.4, 12.5).
Therefore, only code that has access to the destructor is able to use delete. Since the destructor is protected, that means that no one can call delete on a pointer of type Base*. Only subclasses can use the destructor at all (and the only thing that will is the subclass's own destructor, as part of the subobject destruction process).
Of course, the subclass should make its own destructor public, allowing you to delete objects through the subclass type (assuming that is the correct actual type).
NOTE: Actually, other members of Base can do delete (Base*)p; since they have access. But C++ assumes that someone using this construct will not be doing that -- C++ access control only provides guidance to code outside your class.
delete b; effectively performs b->~Base(); deallocate(b);. The first part - calling the destructor - would fail to compile if the destructor is inaccessible (in the same way that calling any other inaccessible method fails).
From my understanding (based on this page), the only case we would like to use the non-virtual and protected destructor in the base class is the following:
#include <iostream>
struct unary_function {
protected:
~unary_function() {
std::cout << "unary_function" << std::endl;
}
};
struct IsOdd : public unary_function {
public:
bool operator()(int number) {
return (number % 2 != 0);
}
};
void f(unary_function *f) {
// compile error
// delete f;
}
int main() {
// unary_function *a = new IsOdd;
// delete a;
IsOdd *a = new IsOdd;
delete a;
getchar();
return 0;
}
therefore, you can only do this:
IsOdd *a = new IsOdd;
delete a;
or
IsOdd c;
never these:
unary_function *a = new IsOdd;
delete a;
therefore, with nonvirtual protected destructor, the compiler would give an error when you try to use this
void f(unary_function *f) {
delete f;
// this function couldn't get compiled because of this delete.
// you would have to use the derived class as the parameter
}
Protected methods and variables of a class (let's call it Base) can only be accessed by derived classes. Thus, if you call delete on a pointer of type Base outside a derived class, it will try to call Base::~Base() (Base's destructor), but since it is protected, it cannot be called, which thus results in a compilation error.
According to the specification, the destructor of a base class must only be declared protected and non-virtual (to not allow deletion of a derived object through a Base pointer), or public and virtual (to allow safe deletion of a derived object through a Base pointer).
If a destructor is declared public and non-virtual, it results in undefined behaviour if a pointer of type Base which points to a derived class is deleted.
The two options:
Non-virtual protected destructor - Base pointer to Derived cannot be deleted:
class Base {
public:
Base() {
std::cout << "Base ctor called.\n";
}
protected:
~Base() {
std::cout << "Base dtor called.\n";
}
};
class Derived : public Base {
public:
Derived() {
std::cout << "Derived ctor called.\n";
}
~Derived() {
std::cout << "Derived dtor called.\n";
}
};
Base *foo = new Derived;
delete foo; // compilation error
... as mentioned in your question.
Public virtual destructor - allows a pointer of type Base to a Derived object to be deleted. First the Derived destructor is called, and then the Base destructor is called:
class Base {
public:
Base() {
std::cout << "Base ctor called.\n";
}
virtual ~Base() {
std::cout << "Base dtor called.\n";
}
};
class Derived : public Base {
public:
Derived() {
std::cout << "Derived ctor called.\n";
}
~Derived() override {
std::cout << "Derived dtor called.\n";
}
};
Base *foo = new Derived;
delete foo;
Output:
Base ctor called.
Derived ctor called.
Derived dtor called.
Base dtor called.
Why are all destructors, ~D(),~C(),~B(),~A() being called in the example below?
There is only one virtual destructor: that of A.
Here is the code:
#include<iostream>
using namespace std;
class A
{
public:
virtual ~A()
{
cout<<"destruct A\n";
}
};
class B:public A
{
public:
~B()
{
cout<<"destruct B\n";
}
};
class C:public B
{
public:
~C()
{
cout<<"destruct C\n";
}
};
class D:public C
{
public:
~D()
{
cout<<"destruct D\n";
}
};
int main()
{
A* ptr = new D();
delete ptr;
return 0;
}
Once A's destructor is declared virtual, the destructors of all derived classes are also virtual, even if they aren't explicitly declared as such.. So the behaviour you see is exactly what is expected
The destruction order in derived objects goes in exactly the reverse
order of construction: first the destructors of the most derived
classes are called and then the destructor of the base classes.
A destructor can be defined as virtual or even pure virtual. You would
use a virtual destructor if you ever expect a derived class to be
destroyed through a pointer to the base class. This will ensure that
the destructor of the most derived classes will get called:
A* b1 = new B;//if A has a virtual destructor
delete b1;//invokes B's destructor and then A's
A* b1 = new B;//if A has no virtual destructor
delete b1;//invokes A's destructor ONLY
If A does not have a virtual destructor, deleting b1 through a pointer
of type A will merely invoke A's destructor. To enforce the calling of
B's destructor in this case we must have specified A's destructor as
virtual:
virtual ~A();
REFERENCE
As #juanchopanza said - declaring the base destructor virtual means all descendants have virtual destructors. This inherited virtuality is the same for any methods, not just destructors.
It's why I have interviewed people who didn't know what the keyword did because they had only ever had to override methods derived from a framework, so they were all virtual (sigh).
#include <iostream>
using namespace std;
class base
{
int a;
public:
base() {a =0;}
};
class derv :public base
{
int b;
public:
derv() {b =1;}
};
int main()
{
base *pb = new derv();
delete pb;
}
I don't have a virtual destructor in derv class, does it delete only base part of derv object??
It might.
Because base does not have a virtual destructor, your code exhibits undefined behavior. Anything might happen. It might appear to work as you expect. It might leak memory. It might cause your program to crash. It might format your hard drive.
A citation was requested. C++11 ยง5.3.5/3 states that, for a scalar delete expression (i.e., not a delete[] expression):
if the static type of the object to be deleted is different from its dynamic type, the static type shall be a base class of the dynamic type of the object to be deleted and the
static type shall have a virtual destructor or the behavior is undefined.
The static type (base) is different from the dynamic type (derv) and the static type does not have a virtual destructor, so the behavior is undefined.
In your source code there is no memory leak, since you don't have any member variable that is created dynamically.
Consider the modified example below Case 1:
#include <iostream>
using namespace std;
class base
{
int a;
public:
base() {a =0;}
~base()
{
cout<<"\nBase Destructor called";
}
};
class derv :public base
{
int *b;
public:
derv() { b = new int;}
~derv()
{
cout<<"\nDerv Destructor called";
delete b;
}
};
int main()
{
base *pb = new derv();
delete pb;
}
In this case the output will be,
Base Destructor called
In this case there is a memory leak, because 'b' is created dynamically using 'new' which should be deleted using 'delete' keyword. Since derv destructor is not being called it's not deleted so there is memory leak.
Consider the below case 2:
#include <iostream>
using namespace std;
class base
{
int a;
public:
base() {a =0;}
virtual ~base()
{
cout<<"\nBase Destructor called";
}
};
class derv :public base
{
int *b;
public:
derv() { b = new int;}
~derv()
{
cout<<"\nDerv Destructor called";
delete b;
}
};
int main()
{
base *pb = new derv();
delete pb;
}
In the case 2 output will be,
Derv Destructor called
Base Destructor called
In this case there is no memory leak.because derv destructor is called and b is getting deleted.
Destructor can be defined as Virtual in base class to make sure the derived class destructor to be called when we delete base class pointer which is pointing to derived class object.
We can say 'Destructor must be virtual when derived class has dynamically created members'.
There is no memory leak in your code. There would have been a memory leak if you needed to free some memory in the derived class destructor.