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();
}
In C# 8.0 and earlier, the return types of an override method and the overridden base method must be the same. You cannot override a non-virtual or static method. The overridden base method must be virtual , abstract , or override . An override declaration cannot change the accessibility of the virtual method.
Similarly, you can prevent a method from being overridden by subclasses by declaring it as a final method. An abstract class can only be subclassed; it cannot be instantiated. An abstract class can contain abstract methods—methods that are declared but not implemented.
Can you allow class to be inherited, but prevent the method from being over-ridden? Yes, just leave the class public and make the method sealed.
The final way of preventing overriding is by using the final keyword in your method. The final keyword puts a stop to being an inheritance. Hence, if a method is made final it will be considered final implementation and no other class can override the behavior.
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
.
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();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With