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(); }
Related
#include <iostream>
using namespace std;
#define debug(x) cout << #x << ": " << (x) << endl;
class Base {
public:
void f() { cout << "Base:f()" << endl; }
~Base() { cout << "Base:~Base()" << endl; }
};
class A : public Base {
public:
~A() { cout << "A:~A()" << endl; }
};
int main() {
{
A a;
static_cast<Base>(a);
}
return 0;
}
In this code
I call the static_cast to covert the A to Base,
the output tells me that it calls the ~Base() twice?
why the static_cast make the destructor be called?
static_cast<Base>(a); constructs a temporary Base, which is copied from a. After the full expression the temporary gets destroyed, the destructor of Base is called.
After that, when get out of the scope a gets destroyed, the destructor of A and Base are called in order. Note that this has nothing to do with the static_cast.
#include <iostream>
#include <memory>
using namespace std;
class Base
{
public:
virtual void foo() = 0;
protected:
int num{ 1 };
public:
Base() {
cout << "Base class constructor" << endl;
}
virtual ~Base()
{
cout << "Base class destructor " << endl;
}
private:
};
class Derive : public Base {
public:
Derive() {
cout << "Derive class constructor" << endl;
}
~Derive() {
cout << "Derive class destructor " << endl;
}
public:
void foo() override{
cout << "Derive class Foo function" << endl;
}
};
int main() {
unique_ptr<Base> b = make_unique<Base>(new Derive());
b->foo();
}
I get below error when I build this code.
in instantiation of function template specialization 'std::make_unique<Base, Derive *>' requested here unique_ptr b = make_unique(new Derive());
unimplemented pure virtual method 'foo' in 'Base' virtual void foo() = 0;
Does anyone know what is the reason of this error?
Note: I tried on https://godbolt.org/ and selected clang 11
In your main() function, do this instead:
unique_ptr<Base> b(new Derive());
This is because std::make_unique() takes the actual constructor arguments. You can't do that with polymorphism, but there's nothing wrong with directly instanstiating a std::unique_ptr directly with a heap allocated resource.
Do prefer std::make_unique() where it makes sense, though. This just isn't one of those cases.
I have the following code:
class A {
public:
A() { cout << "A()" << endl; }
void f() { cout << "A" << endl; }
};
class B : public A {
public:
B() { cout << "B()" << endl; }
void f() { cout << "B" << endl; }
void ff() { cout << "ff()" << endl; }
};
int main()
{
A a = B();
B b;
a = b;
}
How calling A a = B(); will be different from A a = A();? Why is the conversion from derived class to base class possible?
When you do A a = B();, copy constructor of class A should be invoked after default constructor of class B has been invoked (Note: Compiler may remove unnecessary copy using copy elison).
A(const A& other)
{
}
Since, object of class B can be passed to copy constructor of class A, it will be allowed but you may experience object-slicing.
If you are curious to know "how is it possible to pass a derived class object to a method accepting a reference to the base class", read the following:
Is it possible to pass derived classes by reference to a function taking base class as a parameter
In the following code, how can I access Base::g() from pBase? (and still get "pBase->g();" to work as it does below)
#include <iostream>
using namespace std;
class Base
{
public:
virtual void f(){ cout << "Base::f()" << endl; }
virtual void g(){ cout << "Base::g()" << endl; }
void h(){ cout << "Base::h()" << endl; }
};
class Derived : public Base
{
public:
void f(){ cout << "Derived::f()" << endl; }
virtual void g(){ cout << "Derived::g()" << endl; }
void h(){ cout << "Derived::h()" << endl; }
};
int main()
{
Base *pBase = new Derived;
pBase->f();
pBase->g();
pBase->h();
Derived *pDerived = new Derived;
pDerived->f();
pDerived->g();
pDerived->h();
return 0;
}
Output is:
Derived::f()
Derived::g()
Base::h()
Derived::f()
Derived::g()
Derived::h()
Also, is Derived::f() exactly the same as Derived::g()? (ie. automatically defined as virtual?)
Use pBase->Base::g(); to force the call of g in Base.
Yes, Derived::f is virtual. I personally find the re-emphasising of virtual to be in poor taste. Since C++11, you can use the override specifier on overridden functions, and then a compiler issues a diagnostic if virtual is dropped from the base class.
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).