0

I am trying to understand if my mistake comes from a design problem or a code error. My search pointed me out to Slicing issue but I don't see this being the issue here.

#include <string>
#include <iostream>
#include <vector>

    class BaseA {
    public:
        BaseA(const std::string &n)
            : name(n)
        {}
        virtual ~BaseA() 
        {};
        virtual void print() const
        {
            std::string str("");
            str += name;
            std::cout << str << std::endl;
        }

    protected:
        std::string name;
    };

    class BaseB : public BaseA {
    public:
        BaseB(const std::string &n, const std::string &v)
            : BaseA(n), value(v)
        { 
            load();
        }
        virtual ~BaseB() 
        {};
        virtual void load(){
             c = 'B';
        }
        char getC() {
            return c;
        }
        void print() const{
            std::string str("");
            str += name;
            str += ' ';
            str += value;
            std::cout << str << std::endl;
        }
    protected:
        char c;
    private:
        std::string value;
        int data = 0;
    };

    class BaseC : public BaseB {
    public:
        BaseC(const std::string &n, const std::string &v)
            : BaseB(n, v) 
        {
        }
        void load() override{
             c = 'C';
        }
    };

    int mainTest() 
    {
        std::vector<BaseB*> vec;
        vec.push_back(new BaseB("John", "singer"));
        vec.push_back(new BaseC("Raoul", "wannabe"));   
        for (BaseB *obj : vec)
        {
            obj->print();
            std::cout << "load class: " << obj->getC() << std::endl;
        }
        return(0);
    };

I would expect the result to be:

John singer 
load class: B 
Raoul wannabe 
load class: C

but I get B for both. Does it mean that in the constructor, it is not possible to use an overridden class? thanks

Windrider
  • 57
  • 6

1 Answers1

3

It's not impossible, but it may not do what you want.

Recall that for BaseC, the construction order is BaseA, BaseB, BaseC.

While BaseB is being constructed (constructor executing), there is no such object as a BaseC, even if it is being constructed as part of a BaseC construction.

The standard therefore mandates that during the constructor (and destructor) of BaseB, calling load() will result in BaseB::load() being called. Not BaseC::load()

Richard Hodges
  • 68,278
  • 7
  • 90
  • 142