[C++] 模板

xiaoxiao2021-02-28  77

定义模板时, 使用关键字typename还是class没有区别,两个都可以用。

1 函数模板

下例是函数模板的定义及使用,可以看出,函数模板的调用方式同一般函数:

// returns 0 if the values are equal, 1 if v1 is larger, -1 if v1 is smaller template <typename T> // 模板参数列表, 由逗号分隔,一个或多个,不能为空 int compare(const T &v1, const T &v2) { if (v1 > v2) return 1; if (v1 < v2) return -1; return 0; } int main () { // 编译器实例化为int compare(const int&, const int&) cout << compare(1, 0) << endl; // 编译器实例化为int compare(const string&, const string&) string s1 = "hi", s2 = "world"; cout << compare(s1, s2) << endl; return 0; }

对于内联函数模板,inline关键字必须位于模板参数列表和函数返回类型的中间。

// OK: inline specifier follows template parameter list template <typename T> inline T min(const T&, const T&); // !!! ERROR: inline 不能放在template关键字之前 inline template <typename T> T min(const T&, const T&);

2 类模板

类模板的定义形式及使用如下所示:

template <class Type> class Queue { public: Queue (); // default constructor Type &front (); // return element from head of Queue const Type &front () const; void push (const Type &); // add element to back of Queue void pop(); // remove element from head of Queue bool empty() const; // true if no elements in the Queue private: // ... }; int main() { Queue<int> qi; // Queue that holds ints Queue< vector<double> > qc; // Queue that holds vectors of doubles Queue<string> qs; // Queue that holds strings return 0; }

3 模板编译模型

不同于一般函数和类定义,对于模板,编译器要求看到调用模板函数或模板类的成员函数时,也要求能看到定义。C++定义了两种编译模板代码的模型:包含编译模型(Inclusion Compilation Model) 和单独编译模型(Separate Compilation Model), 以支持声明和实现,或定义和实现分别放在头文件和源文件中的项目组织形式。

否则,要通过编译,模板的实现必须放在头文件中。

3.1 包含编译模型 (Inclusion Compilation Model)

这种编译模型,所有的编译器都支持。

// 头文件 utlities.h #ifndef UTLITIES_H // header gaurd (Section 2.9.2, p. 69) #define UTLITIES_H template <class T> int compare(const T&, const T&); // other declarations #include "utilities.cc" // get the definitions for compare etc. #endif ---------------------------------------------------------------- // 源文件 utlities.cc template <class T> int compare(const T &v1, const T &v2) { if (v1 > v2) return 1; if (v1 < v2) return -1; return 0; } // other definitions

用VS2010测试:

//file: my_template.h #ifndef MY_TEMPLATE_H #define MY_TEMPLATE_H template<typename T> int compare(const T&, const T&); #include "my_template.cpp" # Most import line for build #endif ----------------------------------------------------- //file: my_template.cpp #include "stdafx.h" // 注意,这里不能加 #include "my_template.h", 加了就无法编译通过。 template<typename T> int compare(const T& v1, const T& v2) { if (v1 > v2) return 1; if (v1 < v2) return -1; return 0; } ----------------------------------------------------- // file with main: #include "stdafx.h" #include "my_template.h" #include <iostream> using std::cout; using std::endl; int _tmain(int argc, _TCHAR* argv[]) { cout << compare(3, 1) << endl; system("pause"); return 0; } // 可以成功执行,输出 1.

对于函数模板,这种方法ok。

但是测试中发现,对于模板类,如果加了类似 include “source.cpp” 的指令,会出现“函数模板已经定义”的错误,所以,把模板类的实现也放在头文件中,将是省时省力的做法。

3.2 单独编译模型 (Separate Compilation Model)

这种编译模型使用了关键字export。

对于函数,只需在源文件中的函数定义前加export关键字。

// the template definition goes in a separately-compiled source file export template <typename Type> Type sum(Type t1, Type t2) /* ...*/

对于类,略有不同:

// 头文件 template <class Type> class Queue { ... }; ------------------------------------------------------------- // 源文件 export template <class Type> class Queue; #include "Queue.h" // Queue member definitions

由于VS2010 说它不支持export关键字,这种编译模型没测试过。


[1] C++ Primer Chapter 16 Templates and Generic Programming

转载请注明原文地址: https://www.6miu.com/read-2629166.html

最新回复(0)