Насколько я понимаю, вы в основном хотите получить доступ к переопределенным функциям NodeBase
.Вы все еще можете сделать это с помощью шаблонов.Я не собираюсь предлагать изменения кода в вашем дизайне, потому что я предполагаю, что вы упростили это, чтобы дать нам представление о том, что вы хотите, чтобы ваш код делал.
С учетом сказанного, давайте предположим, что класс NodeBase
базовый класс для NodeInt
и NoteDouble
.и это выглядит примерно так (немного упрощенно по сравнению с вашим).
class NodeBase
{
public:
...
virtual void DoSomething()
...
};
class NodeInt : public NodeBase
{
public:
...
virtual void DoSomething() //overridden
{
}
...
};
class NodeDouble : public NodeBase
{
public:
...
void DoSomething()//overriden
{
}
...
};
Давайте также предположим, что наша функция Access выглядит так:
template<typename Type, typename A>
void Access(std::list<TypedNode<Type>, A> node_list)
{
for (auto node : node_list)
{
node.DoSomething();
}
}
Обратите внимание, что наша функция Access теперь может приниматьлюбой тип списка, содержащий TypeNode
из-за TypedNode<Type>
Задача функции Access - просто вызвать DoSomething.это не должно волновать, какой это тип.и оно должно быть выведено на основе того, что вызывать, в зависимости от того, что мы передаем в качестве аргумента вызова Access.
- , если список, переданный в
Access
, является типом <TypedNode<NodeBase>
, вы хотите, чтобы каждый узелдля вызова, NodeBase::DoSomething();
- , если список, переданный
Access
, является типом <TypedNode<NodeInt>
, который вы хотите, чтобы каждый узел вызывал, NodeInt::DoSomething();
- , если список передан
Access
это тип <TypedNode<NodeDouble>
, который вы хотите, чтобы каждый узел вызывал, NodeInt::DoSomething();
Для этого сначала вместо наследования от базового класса давайте наследуем от параметризованного аргумента шаблона.
template<typename Type>
class TypedNode : public Type
Далее мы хотим объявить и определить функцию DoSomething
для нашего TypedNode
класса.
template<typename Type>
class TypedNode : public Type
{
...
void DoSomething();
...
};
template<typename Type>
inline void TypedNode<Type>::DoSomething()
{
Type::DoSomething();//this is where the magic happens.
}
Обратите внимание на Type::DoSomething();
, это позволит нам вызвать DoSomething()
функция базового базового класса.Следует обратить внимание на то, что когда мы инициализируем объект с помощью аргументов шаблона, класс, который используется при инициализации аргумента шаблона, должен иметь член класса с именем DoSomething
, иначе во время компиляции мы получим ошибку.
например;
TypedNode<int> intNode; //wont work because int doesnt have a member DoSomething.
TypeNode<NodeBase> baseNode; //fine.
TypeNode<NodeInt> intNode2; //fine
наконец, основной код, который дает результаты для нас.
int main()
{
std::list<TypedNode<NodeBase>> baseNodeList;
std::list<TypedNode<NodeInt>> intNodeList;
std::list<TypedNode<NodeDouble>> DoubleNodeList;
TypedNode<NodeBase> baseNode;
TypedNode<NodeInt> intNode;
TypedNode<NodeDouble> doubleNode;
baseNodeList.push_back(baseNode);
intNodeList.push_back(intNode);
DoubleNodeList.push_back(doubleNode);
Access(baseNodeList);
Access(intNodeList);
Access(DoubleNodeList);
return 0;
}
вот полный код https://ideone.com/2jEmBO