I was wondering if an elegant solution exists to this problem.
Suppose the following:
class Base {
private:
int data;
protected:
Base(int data) : data(data) { }
int getData() const { return data; }
virtual bool someOp() = 0;
}
class Derived1 : public Base {
private:
int data2;
public:
Derived1(int data, int data2) : Base(data), data2(data2) { }
int getData2() const { return data2; }
bool someOp() override { /* something */ }
}
class Derived2 : public Base {
private:
float data2;
public:
Derived1(int data, float data2) : Base(data), data2(data2) { }
float getData2() const { return data2; }
bool someOp() override { /* something */ }
}
And suppose that I have the total control over the hierarchy so I can assume that Base won't get extended, nor any DerivedX class.
Now I want to store them in a std::vector, if I want to use polymorphism I'm forced to store pointers otherwise object slicing will prevent me to store the additional derived properties. So I'm basically forced to use a std::vector<unique_ptr<Base>>.
But let's assume that I need to store plenty of these objects and I don't want to waste for double heap allocation (the internal std::vector + the object itself) and that at the same time I can assume that:
- the class hierarchy is perfectly defined and won't be extended without knowing it
sizeof(DerivedX)won't be so larger thansizeof(Base)
So I'm wondering if there is an elegant way to keep polymorphism and avoid storing pointers. I could think of some solutions like
class Base {
enum {
DERIVED1,
DERIVED2
} type;
int data;
union {
int derived1data;
float derived2data;
}
bool someOp() {
if (this->type == DERIVED1) ...
else if ..
}
}
But this is clearly not elegant. I could also try to exploit the fact that object slicing shouldn't occur if sizeof(Derived) == sizeof(Base) by using a protected union in Base and accessing it from Derived and casting the address to elements in the std::vector to the desired type (according to an enum) but this sounds ugly too.
Aucun commentaire:
Enregistrer un commentaire