user1553111
user1553111

Reputation:

C++ What is the expected behavior of passing a 'this' pointer to a base class and then store it in as another base class of the child class

So i have a vector<Base> and Base is the base class of multiple children, some of his children may be templated classes. I want to access the child classes from this base class without using dynamic_casting I cant also change the base class to an abstract class. Here is what I did

struct Ainterface { 
    virtual double GetVal() = 0;
};

struct Binterface { 
    virtual bool Getbo() = 0;
    virtual int  Getty()  = 0;
};

struct Base {    
    Base(int id, Ainterface* inter):
    id_(id),
    a_interface_(inter){}

    Base(int id, Binterface* inter):
    id_(id),
    b_interface_(inter){}

    int id_;
    Ainterface* a_interface_;
    Binterface* b_interface_;
};

struct A : Base, Ainterface {
    A():
    Base(1, this),
    val(5.5){}

    double val;
    double GetVal(){return val;}
};

template<typename T>
struct B : Base, Binterface {
    B():
    Base(2, this),
    ty(5){}

    int ty;

    bool Getbo(){ return t_class.get();}
    int Getty(){ return ty;}
    T t_class;
};


...
...

int main(){
    std::vector<Base> base;
    base.push_back(A());
    auto some = base.back();

    switch (some.id_) {
        case 1:
            std::cout << some.a_interface_->GetVal() << std::endl;
            break;
        case 2:
            std::cout << some.b_interface_->Getbo() << some.b_interface_->Getty() << std::endl;
    default:
        break;
    }
   return 0;
}

OUTPUT

  5.5

Is this a safe thing to do? Is there a better way to achieve this?

Thanks

Upvotes: 0

Views: 66

Answers (1)

Tobias Brandt
Tobias Brandt

Reputation: 3413

When you declare a variable of type vector<Base>, the vector only allocates space for values of class Base, not any of the derived classes. When you push back a temporary A it is actually sliced and becomes a Base. The GetVal method only works by accident as the memory in which the temporary resided hasn't been reclaimed yet.

So, no, this is not a safe thing to do. It is undefined behaviour.

If you want to have a vector of objects that can vary in type, you have to use some kind of pointer. Ideally, you would use a vector<shared_ptr<Base>>.

Upvotes: 4

Related Questions