2015-03-30 3 views
-2

Итак, у меня есть 2 класса, шаблонный номер Node<T> и без него номер Context. У меня есть несколько методов в Context, которые должны возвращать любой тип Node<T>.Метод C++, который может возвращать различные шаблонные типы

Например, иногда нужно будет возвращать Node<double> и иногда Node<int> и т.д. У меня также есть некоторые методы, которые я хотел бы иметь, что принимать любой тип Node<T> в качестве параметра.

Есть ли способ сделать это, который не включает отдельные методы в Context для каждого возможного случая?

class Node 
{ 
    T Val; 
public: 
    Node(T value) : Val(val) {} 
    T getVal() { return Val; } 
} 

class Context 
{ 
    Node<type>* divide(Node<type>* LHS, Node<type>* RHS) 
    { 
    type Solution LHS->getVal()/RHS->getVal(); 
    return new Node<type>(Solution); 
    } 
} 

К примеру, здесь, я хочу вернуться либо Node<double> если ответ заканчивает тем, что десятичное, то я хочу, чтобы вернуть Node<int>. Он вернет Node<double> с разрешением Node->Val;. В другое время операция вернет Node<int> (например, 4/2), поэтому вместо этого она вернет Node<int>. Это сокращенный пример того, что я хочу сделать, но его та же идея.

+0

звучит как случай для полиморфизма –

+5

Я думаю, что вы должны быть более desciptive. Вы либо хотите [полиморфизм] (http://www.cplusplus.com/doc/tutorial/polymorphism/), либо [templated function] (http://www.cplusplus.com/doc/tutorial/templates/) – dwcanillas

+1

" У меня есть 2 объекта, Object и Context. " Думаю, вы имели в виду ** классы **. «иногда ему нужно будет вернуть объект, а иногда и объект», пожалуйста, перефразируйте это. Похоже, ты сделал опечатку. – Hiura

ответ

1

Полиморфизм, как предполагалось, с виртуальными методами не может быть достигнут на C++, если вам нужны разные типы возвращаемых данных .. если вы не используете что-то вроде boost::any или не возвращаете непрозрачные void *.

Для того чтобы C++ работал, если вам нужны разные типы возвращаемых данных, вам нужны разные подписи и, следовательно, 2 разных метода, однако C++ имеет синтаксический сахар, позволяя обработчику обработать это (шаблоны) так, чтобы кодер только что написал 1 метод один раз.

template < typename T> 
class Node{ 
    //... 
}; 

class Container{ 


public: 

    template< typename T> 
    Node< T> * getNode(){ 

    } 
}; 

возможная реализация:

#include <stack> 
#include <string> 
#include <typeinfo> 

class Container{ 
    std::stack<void *> data; 
    std::stack<std::string> names; 
public: 


    //push a node on the stack (you have to allocate it) 
    template< typename T> 
    void addNode(Node< T> * p){ 
     data.push(static_cast<void*>(p)); 
     names.push(typeid(T).name()); 
    } 


    template< typename T> 
    Node< T>* removeNode(){ 
     if(names.top()==typeid(T).name()){ 
      names.pop(); 
      Node< T>* node = reinterpret_cast<Node<T>*>(data.top()); 
      data.pop(); 
      return node; 
     } 
     return NULL; //returns nullptr; 
    } 
}; 

конечно, это просто рабочий пример (если вы Node определены где-то). Чтобы показать вам возможный способ (в буквальном смысле это самый простой пример, о котором я могу думать, но вы можете повысить производительность и использовать его для разработки решения своей проблемы).

Пример использования:

Container c; 
Node<double> n1* = new Node<double>(5.0); 
Node<double> n2* = new Node<double>(3.0); 
Node<int> n3* = new Node<int>(100); 
c.addNode(n1); 
c.addNode(n2); 
c.addNode(n3); 
//since I used a stack now I check node in reversed order 
cout<<  c.getNode<double>() == n3 <<endl; // false! n3 use "int" 
cout<<  c.getNode<int>() == n3 <<endl; //true! 
cout<<  c.getNode<double>() == n2 <<endl; //true! 
cout<<  c.getNode<int>() == n1 <<endl; //false! n1 use double 
cout<<  c.getNode<double>() == n1 <<endl; //true 

delete n1; 
delete n2; 
delete n3; 
Смежные вопросы