Reputation: 63
In a project of mine I encountered this problem where the polymorphism seemingly doesn't work. Derived classes don't seem to override the base class, but no errors ocurr either.
This is a simplification of the code, but it generates the same problem. The usage of vector
and unique_ptr
is the same as in my project, I suspect that my usage of those is what's causing the problem.
I expect
void print() override
{
printf("B HEJ");
}
to override
virtual void print()
{
printf("A HEJ");
}
, but it doesn't. Why?
Here is the complete source code:
#include <iostream>
#include <string>
#include <memory>
#include <vector>
class A
{
public:
virtual void print()
{
printf("A HEJ");
}
};
class B : public A
{
public:
void print() override { printf("B HEJ"); }
};
int main()
{
std::vector<std::unique_ptr<A>> ass;
ass.emplace_back(std::make_unique<A>(B()));
ass[0]->print();
std::cin.get();
}
Upvotes: 6
Views: 187
Reputation: 117298
You need to make_unique<B>
and add a virtual
destructor to the base class.
make_unique<B>
creates a unique_ptr<B>
that, if B
is derived from A
will be accepted by (moved into) a unqiue_ptr<A>
.make_unique<A>(B())
copy constructs an A
from a B
, slicing the B
(only the A
part of the default constructed B
will be copied).virtual
method chain is preserved, the most derived method is called. Not having a virtual
destructor makes sure that only the base class destructor is called when you have a vector
of base class pointers. The result is more often than not catastrophic. You want the destructor(s) of the most derived classes to be called - so make the base class destructor virtual
.#include <iostream>
#include <string>
#include <memory>
#include <vector>
class A
{
public:
virtual ~A() = default;
virtual void print()
{
printf("A HEJ");
}
};
class B : public A
{
public:
void print() override { printf("B HEJ"); }
};
int main()
{
std::vector<std::unique_ptr<A>> ass;
ass.emplace_back(std::make_unique<B>());
ass[0]->print();
}
Upvotes: 9
Reputation: 62583
You have an error here:
ass.emplace_back(std::make_unique<A>(B()));
This line creates a unique pointer to A
, initializing it by copying from default-constructed B
. It is equivalent with new A(B())
for naked pointers.
You need to create a unique pointer to B
, so your code should look like:
ass.emplace_back(std::make_unique<B>());
While on it, do not forget to add virtual destructor to A
.
Upvotes: 12