Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why isn't this method being overridden?

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();
}
like image 826
axel Avatar asked Aug 20 '21 18:08

axel


People also ask

Which methods Cannot be overridden in C#?

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.

How do we prevent a method from being overridden?

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.

How can you allow a class to be inherited but prevent a method from being overridden in C#?

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.

Can you prevent a class from overriding?

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.


Video Answer


2 Answers

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.

like image 154
SergeyA Avatar answered Oct 22 '22 15:10

SergeyA


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).
  • As long as the 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();
}
like image 22
Ted Lyngmo Avatar answered Oct 22 '22 14:10

Ted Lyngmo