2017-06-21 26 views
-4

我对C++中的模板主题颇为陌生。为什么在下面的玩具示例代码中,我们必须在类和每个函数的名称前加上template <class T>(这意味着为什么我们需要它)?在声明类和函数时,在C++中使用模板<class T>

是否有可能修改代码不使用template <class T>无处不在?

#include <iostream> 
#include <vector> 
#include <cstdlib> 
#include <string> 
#include <stdexcept> 

using namespace std; 

template <class T> 
class Stack { private: 
    vector<T> elements; 

    public: 
    void push(T const &); 
    void pop(); 
    T top(); 
    bool empty(); }; 

template <class T> 
void Stack<T>::push(T const &elem) { 
    elements.push_back(elem); } 

template <class T> 
void Stack<T>::pop() { 
    if (elements.empty()) { 
     throw out_of_range("Stack<>::pop(): empty stack"); 
    } else { 
     elements.pop_back(); 
    } 
} 

template <class T> 
T Stack<T>::top() { 
    if (empty()) { 
     throw out_of_range("Stack<>::top(): empty stack"); 
    } 
    return elements.back(); 
} 

template <class T> 
bool Stack<T>::empty() { 
    return elements.empty(); 
} 


int main() { 
    try { 
     Stack<int> intStack;  // Stack of ints 
     Stack<string> stringStack; // Stack of strings 

     // Manipulate integer stack 
     intStack.push(7); 
     cout << intStack.top() << endl; 

     // Manipulate string stack 
     stringStack.push("hello"); 
     cout << stringStack.top() << std::endl; 
     stringStack.pop(); 
     stringStack.pop(); 
    } 
    catch (exception const &ex) { 
     cerr << "Exception: " << ex.what() << endl; 
     return -1; 
    } 
} 
+5

什么是“模板标题”? – teivaz

+0

模板没有标题。如果你不想使用模板,为两个不同的数据类型'std :: string'和'int'定义两个类。 – P0W

+0

“模板标题”我的意思是'模板'。那么我应该怎么称呼它?我说我对这个话题很陌生。请更容易理解。 – cerebrou

回答

4

您必须在每个成员定义中包含template <class T>,因为这是成员名称的一部分。

可以将类模板正文中定义的功能,只有一个符合template <class T>

template <class T> 
class Stack { 
    private: 
    vector<T> elements; 

    public: 
    void push(T const &) { 
     elements.push_back(elem); } 
    void pop() { 
     if (elements.empty()) { 
      throw out_of_range("Stack<>::pop(): empty stack"); 
     } else { 
      elements.pop_back(); 
     } } 
    T top() { 
     if (empty()) { 
      throw out_of_range("Stack<>::top(): empty stack"); 
     } 
     return elements.back(); } 
    bool empty() { 
     return elements.empty(); } }; 
2

C++是一种statically typed语言。

既然是这种情况,说我想要一个函数来检查两个值的最小值或最大值。

我可以创建一个功能类似如下:

int max(int a, int b) { return (a > b) ? a : b; } 

int类型这只作品。如果我想要一个用于doubleuint64_tFooBarClass,我将需要创建额外的功能:

double max(double a, double b) { return (a > b) ? a : b; } 
uint64_t max(uint64_t a, uint64_t b) { return (a > b) ? a : b; } 
FooBarClass max(FooBarClass a, FooBarClass b) { return (a > b) ? a : b; } 

为什么在下面的玩具示例代码做,我们必须先于类的每个功能与模板名称?

在C++中,template是一种引入名为"generics"的概念的方法。使用泛型,您不再需要关心自己为每种类型创建函数,类型将从模板函数签名中推导出来。

所以不是,我可以写:

template < typename T > // the typename or class keywords are synonymous when declaring a template 
T max(T a, T b) { return (a > b) ? a : b; } 

template < typename T >的函数签名的包含物表示编译器,这个函数是一个“通用”的功能,必须进行相应处理。

如果,另一方面,你只是有以下几点:

T max(T a, T b) { return (a > b) ? a : b; } 

编译器会期望T是一个明确的类型(如typedef int T;)。

模板可以被应用到类或函数,并且都在同一时间:

template < typename T > 
class Wrapper { 
    public: 
     Wrapper(const T& val) : _val(val) {} 
     // ... other code 

     template < typename X > 
     operator X() 
     { 
      return static_cast<X>(this->_val); 
     } 

     T operator+(const T& val) 
     { 
      return this->_val + val; 
     } 

     friend std::ostream& operator<<(std::ostream& os, const Wrapper& val) 
     { 
      os << val._val; 
      return os; 
     } 

    private: 
     T _val; 
}; 

int main(int argc, char* argv[]) 
{ 
    Wrapper<int> x(42); 
    // template deduction will call Wrapper::operator X() with X being a double 
    double d = x; 
    // template deduction will call Wrapper::operator X() with X being a long 
    long l = x; 
    // this actually calls T operator+(const T& val) with val = 10 and T = int 
    int i = x + 10; 

    std::cout << "x = " << x << std::endl // 42 
       << "d = " << d << std::endl // 42 
       << "l = " << l << std::endl // 42 
       << "i = " << i << std::endl; // 52 
    return 0; 
} 

还可以显式地定义的模板类型,这是被称为template specialization 和超出的范围这个答案给你对当前模板的理解。

是否有可能修改代码不在任何地方使用模板?

是和否。是的,您可以删除template < class T >签名定义,但如前所述,类/函数的签名具有完全不同的含义。

希望清理一下。如果使用得当,模板在C++中是非常强大的工具。

+0

C++是*静态类型*,而不是*“强类型”*。它允许隐式转换,这可能是有损的。 – IInspectable

相关问题