Reputation:
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
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