Why was destructor of Derived class called in this code?
#include <iostream>
class Base
{
public:
Base() { std::cout << "Base::Base() \n"; }
~Base() { std::cout << "Base::~Base() \n"; }
};
class Derived : public Base
{
public:
Derived() { std::cout << "Derived::Derived() \n"; }
~Derived() { std::cout << "Derived::~Derived() \n"; }
};
Derived foo() { return Derived(); }
int main()
{
const Derived& instance = foo();
}
Why was destructor of Derived class called in this code?
Because the Derived instance created in foo() is going out of scope at the end of main program.
#include <iostream>
using namespace std;
class Base {
public:
Base() {
std::cout << "Base::Base() \n";
}
~Base() {
std::cout << "Base::~Base() \n";
}
};
class Derived: public Base {
public:
int i;
Derived() {
i = 10;
std::cout << "Derived::Derived() \n";
}
~Derived() {
i = 0;
std::cout << "Derived::~Derived() \n";
}
int get() {
return i;
}
};
Derived foo() {
return Derived();
}
int main() {
const Derived& instance = foo();
cout << instance.i << endl;
return 0;
}
The output is as follows:
Base::Base()
Derived::Derived()
10
Derived::~Derived()
Base::~Base()
To make it more interesting, consider a modified main:
const Base& instance = foo();
That code creates a temporary (the object returned by foo) of type Derived and extends the lifetime of the object by binding it to a constant reference of type Base. The lifetime of the temporary will be extended until the reference goes out of scope at which point the object will get destroyed. The code is roughly translated to:
Derived __tmp = foo();
const Base& instance = __tmp;
At the end of the block holding the reference instance, the __tmp variable also goes out of scope and gets deleted. Note that even with no virtual destructor, the appropriate destructor is called, as __tmp is of type Derived (the type returned by the function).
Related
In the following code, the function foo is copy constructing a Base object c from a Derived object d. My question is: are we getting an exact copy? Because I'm not getting the polymorphic behavior I'm expecting
#include<iostream>
class Base
{
public:
virtual void sayHello()
{
std::cout << "Hello Base" << std::endl ;
}
};
class Derived: public Base
{
public:
void sayHello() override
{
std::cout << "Hello Derived" << std::endl ;
}
};
void foo(Base* d)
{
Base* c = new Base(*d);
c->sayHello() ;
}
int main()
{
Derived d;
foo(&d) ; //outputs Hello Base
}
There is no virtual constructor nor copy constructor.
However, it is possible to define a function that behaves like one.
In my case, it is the virtual member function copy() which I added to OP's sample:
#include <iostream>
class Base
{
public:
virtual Base* copy() const { return new Base(*this); }
virtual void sayHello()
{
std::cout << "Hello Base" << std::endl ;
}
};
class Derived: public Base
{
public:
virtual Base* copy() const override { return new Derived(*this); }
void sayHello() override
{
std::cout << "Hello Derived" << std::endl ;
}
};
void foo(Base* d)
{
Base* c = d->copy();
c->sayHello() ;
}
int main()
{
Derived d;
foo(&d) ; //outputs Hello Derived
return 0;
}
Output:
Hello Derived
Live Demo on coliru
The drawback is that every derived class of Base has to provide it to make it function properly. (I've no idea how to convince the compiler to check this for me with any trick.)
A partial solution could be to make copy() pure virtual in the class Base (assuming it is not meant to be instantiable).
you may wonna change the line of new
Base* c = new Derived(*d);
so you have the type Derived in a Base pointer. During runtime it is looked up, which type it is and you get the right output.
let me know if im wrong... just created this out of my mind on the fly.
To answer your question about whether or not this is copy constructing lets add some members. Base will have a member, m_b and Derived will inherit m_b but also have another member m_d
#include <iostream>
struct Base {
const int m_b;
Base() = delete;
Base(const int a_b) : m_b(a_b) {}
virtual void sayHello() {
std::cout << "Base " << m_b << std::endl;
}
};
struct Derived : public Base {
const int m_d;
Derived() = delete;
Derived(const int a_b, const int a_d) : Base(a_b), m_d(a_d) {}
void sayHello() override {
std::cout << "Derived " << m_b << ' ' << m_d << std::endl;
}
};
void foo(Derived* a) {
Base* b = new Base(*a);
b->sayHello(); // Output is "Base 1", 1 was copied from argument a
}
void bar(Derived* a) {
Base* d = new Derived(*a);
d->sayHello(); // Output is "Derived 1 2"
}
int main() {
Derived d(1, 2);
foo(&d);
bar(&d);
return 0;
}
The line:
Base* b = new Base(*a);
Created a Base and so sayHello calls Base's implementation which doesn't know about m_d. However this line does copy m_b from the derived class
The line:
Base* d = new Derived(*a);
Created a Derived and so sayHello calls Derived's implementation which copied both m_b and m_d
Expected polymorphic behavior will come into existence when the Base class pointer points to Derived class object. Then at run time the actual type of object pointed to by the Base class pointer will be checked and appropriate function will get called.
Base* c = new Base(*d); // <<-- case of object slicing
Here, c points to Base class object. Therefore, c->sayHello() ; is bound to call the Base::sayHello() at runtime.
are we getting an exact copy?. No since you are creating a Base object due to new Base. Due to object slicing the Base part of the *d object is passed to copy c'tor and what you get is corresponding Base object.
Base *c = new Derived(*d); will give the expected behavior.
The following is an abstract of my code:
Base class:
#include <iostream>
using namespace std;
class Base {
public:
Base() { cout << "Base constructor" << endl; }
~Base() { cout << "Base destructor" << endl; }
virtual void func(void) const { cout << "base" << endl; }
};
Derived class:
#include "Base.h"
class Derived : public Base {
public:
Derived() { cout << "Derived constructor" << endl; }
~Derived() { cout << "Derived destructor" << endl; }
void func(void) const { cout << "derived" << endl; }
};
Test class:
#include "Derived.h"
class Test {
public:
const Base& base;
Test(const Base& _base) : base(_base) { cout << "Test constructor" << endl; }
void test() { base->func(); }
~Test() { cout << "Test destructor" << endl; }
};
main function for testing:
#include "Test.h"
int main(void) {
Test* t = new Test(Derived());
t->test();
return 0;
}
When I run the main function, the Base version of func is being called.
However, if I change the main function to the following:
#include "Test.h"
int main(void) {
Derived d;
Test* t = new Test(d);
t->test();
return 0;
}
The Derived version of func is correctly called.
I also tried to change const Base& base in Test to Base* base. And then construct Test using
Test* t = new Test(new Derivec())
It turns out that the Derived version of func is also correctly being called.
I was thinking that if I use either reference or pointer, the polymorphism is going to work.
Can anyone explain to me why the first version does not call the derived class method correctly?
Thanks a lot for helping!
You have a dangling reference problem.
Test* t = new Test(Derived());
You are using a temporary object of type Derived to construct t. The temporary object gets deleted after the constructor of Test returns.
Hence, your program has undefined behavior.
If you use
Derived d;
Test* t = new Test(d);
you get the expected behavior because t does not have a dangling reference.
Also note that
void test() { base->func(); }
should not compile since base is a reference. That lines needs to be:
void test() { base.func(); }
Here is some sample code:
#include <iostream>
class A {
public:
virtual void foo() {
std::cout << "base" << std::endl;
}
A() {
foo();
}
};
class B : public A {
int a;
public:
void foo() {
std::cout << "derived" << std::endl;
}
B(int a) :
a(a) {}
};
int main() {
B o(1);
return 0;
}
I want foo() to get called every time some A derived object is constructed. I do not want to call foo() explicitly in every derived class constructor.
Is there a way to do this in some elegant way?
There is no way you can call an overridden foo() from a base class constructor, no matter what you do. When the base class constructor is called, the derived class object has not been constructed yet, so you cannot call any of its methods or access any of its members. This is true for virtual functions and regular functions as well. In a base class constructor, the this pointer is pointing at the base class, not the derived class.
A potential workaround is to delegate construction to a separate function that clients will have to call instead. Then have that function call foo after construction:
class A {
public:
virtual void foo() {
std::cout << "base" << std::endl;
}
template<typename T, typename ... Args>
static T construct(Args ... args)
{
T newT{ args... };
newT.foo();
return std::move(newT);
}
protected:
A() {
//Construct A
}
};
class B : public A {
int a;
public:
void foo() {
std::cout << "derived" << std::endl;
}
B(int a) :
a(a) {}
};
int main()
{
B o = A::construct<B>(1);
A a = A::construct<A>();
return 0;
}
I'm getting confused why p->a() is calling B::a()?. Is there a paragraph somewhere in the C++ documentation/standard that describes this behavior well?
#include <iostream>
using namespace std;
class A {
public:
A() { cout << "A ctor" << endl; a_instance = this; }
static A *get_instance() { return a_instance; }
static A *a_instance;
void virtual a() { cout << "From base class" << endl; }
};
class B : public A {
public:
B() { cout << "B ctor" << endl; b_instance = this; }
static B *get_instance() { return b_instance; }
static B *b_instance;
void virtual a() { cout << "From derived class" << endl; }
};
A *A::a_instance = 0;
B *B::b_instance = 0;
main()
{
cout << "Create A" << endl;
A ab;
cout << "Create B" << endl;
B abc;
B *ptr = B::get_instance();
A *p = A::get_instance();
cout << "Called from A object type" << endl;
if (p) {
p->a();
}
}
When you create the variable abc, A's constructor sets a_instance to that instance. Despite p being a pointer to an A, since the instance is pointing to a B, it's correctly calling B::a().
To fix this behaviour, you could use the following:
A* A::get_instance()
{
static A a;
return &a;
}
B* B::get_instance()
{
static B b;
return &b;
}
and remove all code that has to do with a_instance and b_instance.
The B constructor calls the A constructor first. That replaces the a_instance that you'd already created.
This chaining of constructors is well defined in the standard. The base is always called first, so that the derived constructor is guaranteed to be working on a valid base object.
What you are experiencing is caused by the design error, which is based on A's constructor initializing the static member using this. Body of this constructor is invoked not only when you are creating the instance of A but also when you are creating the instance of any of its derived classes:
A() { /* ... */ a_instance = this; }
So when you create an instance of type B, before the body of B's constructor is executed, the body of A's constructor is executed at first - this overwrites member a_instance with this within a context of instance of type B, i.e. it makes a_instance to point to this new instance of type B.
What you could do is to place a static variable inside of the getInstance method:
class A
{
public:
static A* getInstance() {
static A s; // <-- instantiated upon first call
return &s;
}
void virtual foo() { std::cout << "From base class" << std::endl; }
protected:
A() { } // <-- protected constructor
~A() { }
A(const A&); // <-- protected copy constructor
A& operator=(const A&); // <-- protected assignment operator
};
then B:
class B : public A
{
public:
static B* getInstance() {
static B s; // <-- instantiated upon first call
return &s;
}
void virtual foo() { std::cout << "From derived class" << std::endl; }
protected:
B() { } // <-- protected constructor
~B() { }
B(const B&); // <-- protected copy constructor
B& operator=(const B&); // <-- protected assignment operator
};
and possible usage:
int main() {
A::getInstance()->foo();
B::getInstance()->foo();
}
that outputs:
From base class
From derived class
B constructor invokes A constructor...
I have got doubt when I was going through the code below. I.e why the destructor of derived class is not called even when an object of derived class goes out of scope in the code below:
#include "stdafx.h"
#include <iostream>
#include <conio.h>
using namespace std;
class ClassA
{
protected:
int width, height;
public:
void set_values(int x, int y)
{
width = x;
height = y;
}
virtual int area()
{
return 0;
}
~ClassA()
{
cout << "base class destructor called" << endl;
}
};
class ClassB : public ClassA
{
public :
int area()
{
return (width * height);
}
~ClassB()
{
cout << "derived class destructor called" << endl;
}
};
int main()
{
ClassA *Ptr = NULL;
ClassB Obj;
Ptr = &Obj;
Ptr->set_values(10, 20);
cout << Ptr->area() << endl;
delete Ptr;
return 0;
}
You should not call delete on Base class pointer pointing to derived class object unless the base class destructor is virtual else what you get is Undefined Behavior.
The destructor in base class needs to be marked virtual.
virtual ~ClassA(){}
Make your destructor virtual in base class. Otherwise, it calls base's destructor.
class ClassA
{
// ...
virtual ~ClassA()
{
cout << "base class destructor called" << endl;
}
};