Search code examples
c++classinheritancesmart-pointers

A unique_ptr defined as base class then cast in as derived class


I would like to see two object printing from two different derived classes, and the key is to cast the object to derived class after being define as base. Here is the code:

#include <iostream>
#include "memory"

using namespace std;

template<class T>
class Base
{
public:
    Base() {};
    ~Base() {};
    void Print()
    {
        std::cout << "Print from Base" << std::endl;
    }
};

class Derived1: public Base<int>
{
public:
    Derived1() {}
    void Print()
    {
        std::cout << "Print from Derived1" << std::endl;
    }
};

class Derived2: public Base<int>
{
public:
    Derived2() {}
    void Print()
    {
        std::cout << "Print from Derived2"<< std::endl;
    }
};

class user
{
public:
    user();
    user(int type)
    :m_type(type)
    {
        switch(type) // change should be done here?
        {
        case 1:
            m_ptr = make_unique<Derived1>(); // m_ptr still base? why not derived
            break;
        case 2:
            m_ptr = make_unique<Derived2>();;
            break;
        default:
            break;
        }
    }

    ~user() {};
    void UserPrint()
    {
        m_ptr->Print();
    }
private:
    std::unique_ptr<Base<int>> m_ptr;
    int m_type;
};

int main()
{
    user a(1);
    user b(2);

    a.UserPrint();
    b.UserPrint();

    return 0;
}

I am expecting to see

Print from Derived1
Print from Derived2

but instead, I am seeing

Print from Base
Print from Base

How to change the code to make it work? I would prefer to change in the constructor of the user(int type).


Solution

  • I think you have some misunderstanding about overriding methods in C++ because you are missing the virtual keywords on (supossed) virtual methods:

    #include <iostream>
    #include "memory"
    
    using namespace std;
    
    template<class T>
    class Base
    {
    public:
        Base() {};
        ~Base() {};
        virtual void Print()
        {
            std::cout << "Print from Base" << std::endl;
        }
    };
    
    class Derived1: public Base<int>
    {
    public:
        Derived1() {}
        void Print() override
        {
            std::cout << "Print from Derived1" << std::endl;
        }
    };
    
    class Derived2: public Base<int>
    {
    public:
        Derived2() {}
        void Print() override
        {
            std::cout << "Print from Derived2"<< std::endl;
        }
    };
    
    class user
    {
    public:
        user();
        user(int type)
        :m_type(type)
        {
            switch(type) // change should be done here?
            {
            case 1:
                m_ptr = make_unique<Derived1>(); // m_ptr still base? why not derived
                break;
            case 2:
                m_ptr = make_unique<Derived2>();;
                break;
            default:
                break;
            }
        }
    
        ~user() {};
        void UserPrint()
        {
            m_ptr->Print();
        }
    private:
        std::unique_ptr<Base<int>> m_ptr;
        int m_type;
    };
    
    int main()
    {
        user a(1);
        user b(2);
    
        a.UserPrint();
        b.UserPrint();
    
        return 0;
    }