Один из подходов к этому состоит в том, чтобы иметь вектор, полный указателей, и иметь функции, которые являются общими для каждого из них: virtual
в базовом классе:
class Alpha {
public:
virtual void dosomething() { /* do something as an alpha */ }
};
class Beta : public Alpha {
public:
void dosomething() { /* do something as a beta */ }
};
class Delta : public Alpha {
public:
void dosomething() { /* do something as a delta */ }
};
vector<Alpha*> v;
v.push_back(new Alpha);
v.push_back(new Beta);
v.push_back(new Delta);
v[1]->dosomething(); // calls Beta's dosomething
Вы должны быть осторожныоднако при таком подходе убедитесь и delete
все, что вы new
положите в контейнер.Вы можете использовать умные указатели и избежать этого предостережения:
vector<shared_ptr<Alpha> > v;
v.push_back(shared_ptr<Alpha>(new Alpha));
v.push_back(shared_ptr<Alpha>(new Beta));
v.push_back(shared_ptr<Alpha>(new Delta));
v[1]->dosomething(); // still calls Beta's dosomething
Причина, по которой вы не хотите иметь вектор Alpha
с (вместо Alpha*
с, которые в порядке), заключается в том, чтоКонтейнеры STL копируют значения, которые вы им даете, и если вы копируете Beta
(или Delta
) как Alpha
, будет вызван только конструктор копирования Alpha
, и полученная информация должна будет вписаться вразмер Alpha
(который, если вы добавили какую-либо информацию в подкласс, будет недостаточно большим), а дополнительная информация, которую имел Beta
(или Delta
), будет потеряна.Это называется нарезкой.