Предположим, у нас есть класс, как следующее:C++: магазин/запомнить тип шаблона класса
class AbstractContainer{
...
};
template <typename T>
class Container : public AbstractContainer {
T someFunction();
};
Теперь есть еще один класс, который имеет переменную-член, который должен хранить один из этих контейнеров. Однако тип шаблона не должен быть фиксированным. Поэтому вместо объявления переменной-члена типа Container
оно объявляется как тип AbstractContainer*
, поэтому указатель на базовый класс. Этот указатель должен иметь возможность хранить все типы классов Container
, независимо от параметра шаблона.
class Interface{
public:
Interface();
void doSth();
private:
AbstractContainer* container;
};
Давайте предположим, что контейнер выполнен в конструкторе Interface
класса, как это:
Interface::Interface(){
if (/* some condition */)
this->container = new Container<int>(25);
} else {
this->container = new Container<float>(25);
}
//here I'd need to remember of which type container is: int or float
}
Так вот мне нужно бы хоть как-то магазин, какой тип мой контейнер (int
или float
) , Я знаю это в этот момент своей программы, и он полностью детерминирован. Мне нужно хранить его, потому что позже я мог бы отдать свой AbstractContainer*
спиной к Container<int>*
или Container<float>*
, например, в другой функции:
void Interface::doSth(){
//here I have to recall what the type was
if(/* type was int */) {
dynamic_cast<Container<int>&>(*(this->container)).someFunction();
} else {
dynamic_cast<Container<float>&>(*(this->container)).someFunction();
}
}
Я думал об использовании enum
, который содержит значения для всех других поддерживаемых типы и сохранение типа в дополнительной переменной-члене этого типа перечисления. Тогда я должен был бы сделать оператор switch
, который проверяет все различные возможности и выполняет правильный перевод. Однако я задавался вопросом, может ли быть более простой способ.
Что я хотел бы сделать, это сохранить тип, используемый в конструкторе Interface
, а затем вызвать его в Interface::doSth
.
EDIT: Я должен четко указать, что функция someFunction
зависит от параметра шаблона T
. Таким образом, это не вариант сделать его виртуальным.
Прежде всего, необходимо ответить, почему 'Интерфейс :: doSth' принимает' 'Контейнер а также 'Container '. Возможно, он вычисляет сумму и не заботится о конкретном базовом типе. В этом случае вы пишете функцию 'virtual double get_sum() const' в' AbstractContainer' и 'переопределяете 'ее в различных' Container '. Есть и другие способы заставить его работать, но выбросить информацию о типе, а затем восстановить его с помощью броска, вероятно, является наихудшим. –
nwp
Как насчет этого возвращает один из элементов контейнера. Затем он вернет «int» для одного и «float» для другого контейнера. Я не могу определить функцию в базовом классе, потому что для этого требуется параметр шаблона 'T'. – user1488118
'boost :: variant' и' static_visitor' могут быть альтернативным дизайном. – Jarod42