Chapter 14 Templates.

Slides:



Advertisements
Similar presentations
面向对象程序设计 QQ群: Object-Oriented Programming 汽车学院.
Advertisements

第14章 c++中的代码重用.
Using C++ The Weird Way Something about c++11 & OOP tricks
4.3函数 4.3.1函数的概念及定义 1、函数的概念: 可以被其它程序调用具有 特定功能的一段相对独立的 程序(模块),称函数。
走向C++之路 WindyWinter WindyWinter感谢诸位前来捧场。
struct 可以在同一個名稱下擁有多種資料型態。使用struct能讓資料的存取和處理更為靈活。
Chap 18 類別與物件 夫有土者,有大物也。有大物者,不可以物。 物而不物,故能物物。 明乎物物者之非物也,豈獨治天下百姓而已哉!
Derived Class 前言 衍生類別的定義 單一繼承 public, protected, 和 privated 基底類別
Chap 3 堆疊與佇列 Stack and Queue.
刘胥影 东南大学计算机学院 面向对象程序设计1 2011~2012第3学期 刘胥影 东南大学计算机学院.
Scope & Lifetime 前言 Local Scope Global Functions & Objects
刘胥影 东南大学计算机学院 面向对象程序设计1 2010~2011第3学期 刘胥影 东南大学计算机学院.
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
刘胥影 东南大学计算机学院 面向对象程序设计1 2011~2012第3学期 刘胥影 东南大学计算机学院.
第七章 搜索结构 静态搜索结构 二叉搜索树 AVL树.
·线性表的定义及ADT ·线性表的顺序存储结构 ·线性表的链接存储结构 · 单向循环链表 · 双链表、双向循环链表 · 一元多项式的加法
哈夫曼编码.
Classes: A Deeper Look, Part 1
第六章 继承性和派生类 胡昊 南京大学计算机系软件所.
刘胥影 东南大学计算机学院 面向对象程序设计1 2010~2011第3学期 刘胥影 东南大学计算机学院.
Object-Oriented Programming:
授课老师:龚涛 信息科学与技术学院 2018年3月 教材: 《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
Object-Oriented Programming in C++ 第一章 C++的初步知识
第三章 C++中的C 面向对象程序设计(C++).
第12章 從C到C++語言 12-1 C++語言的基礎 12-2 C++語言的輸出與輸入 12-3 C++語言的動態記憶體配置
2 C++ 的基本語法和使用環境 親自撰寫和執行程式是學好程式語言的不二法門。本章藉由兩個簡單的程式,介紹C++ 程式的基本結構和開發環境,讓初學者能逐漸建立使用C++ 的信心。
辅导课程六.
第八章 多态性和虚函数 胡昊 南京大学计算机系软件所.
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
切換Dev c++顯示語言 工具->環境選項(V)->介面->language (Chinese TW)
第七章 操作符重载 胡昊 南京大学计算机系软件所.
Chapter6 队列(Queues) The Abstract Data Type
10 多載函數 10.1 多載概論 多載一般函數 多載成員函數 10-3
Classes (2) Lecture 7.
第三章 链表 单链表 循环链表 多项式及其相加 双向链表 稀疏矩阵.
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
常宝宝 北京大学计算机科学与技术系 数据结构(三) 常宝宝 北京大学计算机科学与技术系
第五章 递归与广义表 递归的概念 递归过程与递归工作栈 递归与回溯 广义表.
简单介绍 用C++实现简单的模板数据结构 ArrayList(数组, 类似std::vector)
$9 泛型基础.
潘爱民 C++ Overview 潘爱民
第14讲 运算符重载 运算符重载的概念、方法和规则 运算符重载作为类的成员函数 运算符重载作为类的友元函数 特殊运算符的重载 类型转换函数.
Speaker: Liu Yu-Jiun Date: 2009/4/29
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
第四章 栈和队列 栈 ( Stack ) 队列 ( Queue ) 优先队列 (Priority Queue) 小结.
第11章 從C到C++語言 11-1 C++語言的基礎 11-2 C++語言的資料型態與運算子 11-3 C++語言的輸出與輸入
Inheritance -II.
第三章 数据抽象.
本节内容 类成员的访问控制 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
C++语言程序设计教程 第2章 数据类型与表达式 第2章 数据类型与表达式 制作人:杨进才 沈显君.
C++语言程序设计 C++语言程序设计 第八章 继承 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第十章 多态 第十一组 C++语言程序设计.
C++程序设计 吉林大学计算机科学与技术(软件)学院.
多层循环 Private Sub Command1_Click() Dim i As Integer, j As Integer
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
授课老师:龚涛 信息科学与技术学院 2016年3月 教材:《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
#include <iostream.h>
第二章 Java基本语法 讲师:复凡.
第7章 模板 陈哲 副教授 南京航空航天大学 计算机科学与技术学院.
本节内容 C语言的汇编表示 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
C++语言程序设计 C++语言程序设计 第十一章 异常处理 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第十章 多态 第十一组 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第十章 多态 第十一组 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第十一章 异常处理 C++语言程序设计.
變數與資料型態  綠園.
C++程序语言设计 Chapter 14: Templates.
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
資料結構與C++程式設計進階 C++與資料結構 講師:林業峻 CSIE, NTU 7/ 5, 2010.
Presentation transcript:

Chapter 14 Templates

OBJECTIVES To use function templates to conveniently create a group of related (overloaded) functions. To distinguish between function templates and function-template specializations. To use class templates to create a group of related types. To distinguish between class templates and class-template specializations. To overload function templates. To understand the relationships among templates, friends, inheritance and static members.

Topics 14.1 Introduction 14.2 Function Templates 14.3 Overloading Function Templates 14.4 Class Templates 14.5 Nontype Parameters and Default Types for Class Templates 14.6 Notes on Templates and Friends 14.7 Notes on Templates and static Members

14.1 Introduction Motivation 2018年12月1日11时8分 14.1 Introduction Motivation 实现支持不同数据类型的取最大值函数(例:支持int、double、HugeInt等) 实现支持不同数据类型的Array类(例:支持int、double、HugeInt等)

2018年12月1日11时8分 14.1 Introduction 模板(template): 利用一种完全通用的方法来设 计函数或类而不必预先说明将被使用的每个对象 的类型,利用模板功能可以构造相关的函数或类 的系列,因此模板也可称为参数化的类型。—— 泛型编程(Generic Programming) 在C++语言中,模板可分为类模板(class template)和函数模板(function template)。

Topics 14.1 Introduction 14.2 Function Templates 14.3 Overloading Function Templates 14.4 Class Templates 14.5 Nontype Parameters and Default Types for Class Templates 14.6 Notes on Templates and Friends 14.7 Notes on Templates and static Members

14.2 Function Templates -- review 定义模板: template关键字+尖括号<>括起来的template parameter list(模板参数列表) 模板参数列表: 参数称为formal type parameter(形式类型参数)。 在函数调用时替换为基本数据类型或用户自定义数据 类型。 每个参数都必须以关键词typename (或class )起 头,参数和参数之间必须以逗号分隔,如 template < typename T, typename V>

14.2 Function Templates -- review template < typename T > // or template< classT > T maximum( T value1, T value2, T value3 ) { T maximumValue = value1; // assume value1 is maximum // determine whether value2 is greater than maximumValue if ( value2 > maximumValue ) maximumValue = value2; // determine whether value3 is greater than maximumValue if ( value3 > maximumValue ) maximumValue = value3; return maximumValue; } // end function template maximum

14.2 Function Templates -- review template < typename T > // or template< classT > //模板声明 T maximum( T value1, T value2, T value3 ) //函数模板定义 { T maximumValue = value1; // assume value1 is maximum // determine whether value2 is greater than maximumValue if ( value2 > maximumValue ) maximumValue = value2; // determine whether value3 is greater than maximumValue if ( value3 > maximumValue ) maximumValue = value3; return maximumValue; } // end function template maximum T指定函数返回值、形参以及局部变量的类型 函数调用形式: maximum (1, 2, 3); maximum (int1, int2, int3);

14.2 Function Templates -- 定义 template< typename T > or template< class ElementType > template< typename BorderType, typename FillType > class,typename(关键字):函数模板类型参数,任何内部类型或用户自定义类型。

14.2 Function Templates -- 定义 2018年12月1日11时8分 14.2 Function Templates -- 定义 template <类型形参表>   返回值类型 函数名(形参表)   {   //函数定义体   } <类型形参表>可以有一到若干个类型形参,各形参前需要加上typename/class关键字,表示传递类型,当有多个形参时,各形参间用逗号分隔。 <类型形参表>中的每个形参表示一种数据类型。函数模板“形参表”中至少有一个形参的类型必须用<类型形参表>中的形参来定义。 函数模板只是说明,不能直接执行,需要特化为模板函数后才能执行。 May not include all type para?

如果是用户自定义类型,必须要对<<运算符进行重载 函数模板的参数T必须在模板头中声明 如果是用户自定义类型,必须要对<<运算符进行重载

Creates a function-template specialization of printArray where int replaces T Creates a function-template specialization of printArray where double replaces T Creates a function-template specialization of printArray where char replaces T

14.2 Function Templates -- 函数处理过程 2018年12月1日11时8分 14.2 Function Templates -- 函数处理过程 在程序中说明了一个函数模板 编译系统发现有一个相应的函数调用 例如:printArray( a, ACOUNT ); 编译器寻找和使用最符合函数名和参数类型的函数调用 根据实参中的类型来确认是否匹配函数模板中对应的形参,然后生成一个模板函数(函数模板特化)。(该模板函数的定义体与函数模板的函数定义体相同) 例如:对于int类型的模板特化: void printArray( const int *array, int count ) { for ( int i = 0; i < count; i++ ) cout << array[ i ] << " "; cout << endl; } 编译这个新建的函数 What’s Template function ? void printArray( const int *, int ); void printArray( const double *, int ); void printArray( const char *, int );

Topics 14.1 Introduction 14.2 Function Templates 14.3 Overloading Function Templates 14.4 Class Templates 14.5 Nontype Parameters and Default Types for Class Templates 14.6 Notes on Templates and Friends 14.7 Notes on Templates and static Members

14.3 Overloading Function Templates 2018年12月1日11时8分 14.3 Overloading Function Templates 函数模板可以被重载 允许有其它同名的函数模板,但参数不同 允许有其它同名的函数,但参数不同 编译器挑选最佳匹配的函数或模板 编译器通过匹配过程确定调用哪个函数。 首先,编译器寻找和使用最符合函数名和参数类型的函数调用。如果找不到,则检查是否可以用函数模板产生符合函数名和参数类型的模板函数。 如果有多个函数和调用函数相匹配(且匹配程度相同),编译器会认为有二义性,将产生编译错误 如果没有找到符合函数,将考虑调用强制类型转换

#include <iostream> using namespace std; 2018年12月1日11时8分 #include <iostream> using namespace std; template <class T> void print (const T &a, int b) {cout << "first function called!"<< endl;} template <class T, class T1> void print (const T &a, T1 b) {cout << "second function called!";} void print (const T &a, int c, T1 b) {cout << " third function called!";} void print (const T &a, T1 b, int c) {cout << “fourth function called!";} void print (int a, int b) {cout << " fifth function called!"<< endl;} void print (int a ) {cout << “sixthfunction called!"<< endl;} print(1,2); print(1.1, 2); print(1,2,3);

Topics 14.1 Introduction 14.2 Function Templates 14.3 Overloading Function Templates 14.4 Class Templates 14.5 Nontype Parameters and Default Types for Class Templates 14.6 Notes on Templates and Friends 14.7 Notes on Templates and static Members

14.4 Class Templates --定义 1、类模板通过允许将泛型类实例化为明确类 型的类来实现软件复用 2、类是对问题空间的抽象,而类模板则是对 类的抽象,即更高层次上的抽象。 3、程序中可以首先定义一个类模板,然后通 过使用不同的实参生成不同的类。 4、类模板的定义格式: template <typename <类型参数>> //模板声明 class <类名> // 类定义 { …… };

14.4 Class Templates --定义 每个“类型形参”前必须加typename or class关键字,对类模板进行实例化时,代表某种数据类型;也可以是普通数据类型形参,实例化时代表具体数据 例如: template < typename arg1, int arg2, typename arg3> class myclass   { arg1 buffer[arg2]; arg3 x;  //类的定义体   }; template <类型形参表> class “类模板名” {   private:   私有成员定义   protected:   保护成员定义   public:   公有成员定义 }; 类模板中成员函数可以放在类模板的定义体中(此时与类中的成员函数的定义方法一致)定义,也可以放在类模板的外部来定义,格式为: template <类型形参表> 函数返回类型 类模板名<类型名表>::成员函数(形参) template < typename arg1, int arg2, typename arg3> void myclass<arg1,arg2,arg3>::print() {}

14.4 Class Templates --定义 类模板定义只是对类的描述,它本身还不是一个实实在在的类。 类模板不能直接使用,必须先特化(specialized)为相应的模板类,定义模板类的对象(即实例)后,才可使用(创建对象等)。 可以用以下方式创建类模板的特化及对象。 类模板名<类型实参表> 对象名表; 如:Myclass<int> a; 此处的<类型实参表>要与该模板中的<类型形参表>匹配,要具有同样的顺序和类型,否则会产生错误!

例: 定义一个任意类类型AnyType #include <iostream> using namespace std; template <typename T> class AnyType { T x, y; public: AnyType(T a, T b): x(a), y(b){} T GetX(){return x;} T GetY(){return y;} };

// 测试函数 int main() { AnyType <int> i (1, 2); AnyType <double> d (1.5, 2.7); AnyType <char> c ('a', 'b'); AnyType <char *> s ("Hello", "template class"); cout << "整型类:" << i.GetX() << ", " << i.GetY() << endl; cout << "双精度类:" << d.GetX() << ", " << d.GetY() << endl; cout << "字符类:" << c.GetX() << ", " << c.GetY() << endl; cout << "字符串类:" << s.GetX() << ", " << s.GetY() << endl; return 0; }

14.4 Class Templates --应用 栈:先进后出 数据结构: 操作: 需求:建立栈的类模板,满足不同类型的元素? size:栈的大小 top: 栈顶位置,初始值为-1(空栈) stackPtr :存储栈中元素的一组连续存储空间 操作: push:如果栈不满,则向栈中增加一个元素,top增1 pop: 如果栈不空,则从栈中弹出一个元素,top减1 isEmpty:如果top为-1,则栈为空 isFull:如果top为size-1,则栈满 需求:建立栈的类模板,满足不同类型的元素?

Outline Stack.h (1 of 3) 创建类模板 Stack,包含类型参数 T 成员函数在参数列表中使用类型参数T

Outline (2 of 3) Stack.h Data member stackPtr is a pointer to a T 在类模板之外定义成员函数,必须以模板头(template header)开始

Outline (3 of 3) Stack.h template <类型形参表> 函数返回类型 类模板名<类型名表>::成员函数(形参)

Outline fig14_03.cpp (1 of 3) Create class-template specialization Stack< double > where type double is associated with type parameter T

Create class-template specialization Stack< int > where type int is associated with type parameter T

Outline (3 of 3) fig14_03.cpp 思考:stack类模板如果要处理用户自定义类性,需要用户自定义类型提供什么函数? 2018年12月1日11时8分 Outline fig14_03.cpp (3 of 3) 思考:stack类模板如果要处理用户自定义类性,需要用户自定义类型提供什么函数? 重载赋值运算符,重载数组下标运算符 如何避免main函数中重复的逻辑?使用函数模板

创建函数模板来测试类模板Stack<T> Outline 创建函数模板来测试类模板Stack<T> fig14_04.cpp (1 of 3) Use a function template to process Stack class-template specializations

Outline fig14_04.cpp (2 of 3)

2018年12月1日11时8分 Outline fig14_04.cpp (3 of 3)

Topics 14.1 Introduction 14.2 Function Templates 14.3 Overloading Function Templates 14.4 Class Templates 14.5 Nontype Parameters and Default Types for Class Templates 14.6 Notes on Templates and Friends 14.7 Notes on Templates and static Members

2018年12月1日11时8分 14.5 Nontype Parameters and Default Types for Class Templates(非类型参数和类模板的缺省类型) 非类型的模板形参 特化时作为常量对待 可以有缺省参数 Example Template header: template< typename T, int elements = 10 > Declaration: Stack< double, 100 > salesFigures; 类型形参也可以有默认实参 Template header: template< typename T = string > Declaration: Stack<> jobDescriptions;

先特化再创建对象 定义一个能表示不同大小的栈模板 在编译时指定一个容器类的大小,可以消除使用new的开销以及风险 template <typename T, int size> bool Stack <T,size>::push(const T &x) { if ( !isFull() ) { buffer[ ++top ] = x; return true; } return false; bool Stack <T,size>::pop(T &x) {if ( !isEmpty() ) x = buffer[ top-- ]; Stack <int,100> st1; Stack <double,200> st2; template <typename T, int size> class Stack { T buffer[size]; int top; int tip; public: Stack() {top=-1;} bool push(const T &x); bool pop(T &x); bool isEmpty() const { return top == -1; } bool isFull() const return top == size - 1; }; 先特化再创建对象 在编译时指定一个容器类的大小,可以消除使用new的开销以及风险

14.5 Nontype Parameters and Default Types for Class Templates(无类型参数和类模板的缺省类型) Explicit specializations(显式特化) 当某一特殊数据类型不能使用通用类模板时,可以定制处理(即:重定义该类型的类模板。) 显式特化: Stack< Employee > specialization template<> class Stack< Employee > { … }; 完全代替了通用类模板 Stack< Employee > 没有使用原来类模板的任何内容,甚至可以包含不同的成员 优点:可以兼容已有的基于模板的操作

Topics 14.1 Introduction 14.2 Function Templates 14.3 Overloading Function Templates 14.4 Class Templates 14.5 Nontype Parameters and Default Types for Class Templates 14.6 Notes on Templates and Friends 14.8 Notes on Templates and static Members

14.6 Notes on Templates and Friends 2018年12月1日11时8分 14.6 Notes on Templates and Friends Assume class template X with type parameter T as in: template< typename T > class X 函数声明为类模板的每一个特化的友元 friend void f1();//无参数 f1 is a friend of X< double >, X< string >, etc. 函数声明为类模板的某一类型参数特化的友元 friend void f2( X< T > & );//带参数 f2( X< float > & ) is a friend of X< float > but not a friend of X< string > 关于模板+友元存在的问题:http://www.cnblogs.com/autosar/archive/2011/10/29/2228674.html

template <typenameT, int size> class Stack; template <typename Type, int size2> ostream& operator << (ostream &out, Stack<Type,size2>& s) { Type elem; while (!s.isEmpty()) { s.pop(elem); out<<elem<<endl; } return out; template < typenameT, int size> class Stack { friend ostream& operator << (ostream &out, Stack<T,size>& s); T buffer[size]; int top; int tip; public: Stack() {top=-1;} bool push(const T &x); bool pop(T &x); bool isEmpty() const { return top == -1; } bool isFull() const return top == size - 1; } }; template <class T, int size> bool Stack <T,size>::push(const T &x) { if ( !isFull() ) { buffer[ ++top ] = x; return true; } return false; } bool Stack <T,size>::pop(T &x) {if ( !isEmpty() ) { x = buffer[ top-- ]; return true; } return false; } // 测试函数 int main() Stack <int,100> st1; for (int i=0; i<=10;i++) { st1.push(i*10); cout<<st1; Stack <double,200> st2; return 0;

14.6 Notes on Templates and Friends 另一个类的成员函数可以声明为类模板每一个特化的友元(无参数) friend void A::f3(); f3 of class A is a friend of X< double >, X< string >, etc. 另一个类的成员函数可以声明为类模板某个类型参数特化的友元(带参数) friend void C< T >::f4( X< T > & ); C< float >::f4( X< float > & ) is a friend of X< float > but not a friend of X< string >

14.6 Notes on Templates and Friends 另一个类可以声明为类模板的每一个特化的友元 friend class Y; (无类型参数) Every member function of class Y is a friend of X< double >, X< string >, etc. 另一个类可以声明为类模板的某个类型参数特化的友元 friend class Z< T >; (有类型参数) Class-template specialization Z< float > is a friend of X< float >, Z< string > is a friend of X< string >, etc.

模版类的友元函数 友元类 template<typename T> template<class T> class linkedStack; template <typename T> class Node { friend linkedStack<T>; private: T data; Node<T> *link; //指向下一个 }; template < typename T> ostream& operator << (ostream &out, linkedStack<T > &s) { T elem; while (!s.IsEmpty()) { s.Delete(elem); out<<elem<<endl; } return out; template<class T> class linkedStack { friend ostream& operator << (ostream &, linkedStack<T>&); public: linkedStack () { top = 0; } ~linkedStack(); bool IsEmpty() const { return top == NULL; } linkedStack<T> & Add(const T&x); linkedStack<T> & Delete (T &x); private: Node<T> *top; }; 模版类的友元函数 友元类

template<class T> linkedStack<T>::~linkedStack() { Node<T> *next; while (top != 0) { next = top->link; delete top; top = next; } linkedStack<T> &linkedStack<T>::Add(const T&x) { Node<T> *p = new Node<T>; p->data = x; p->link = top; top = p; return *this; template<class T> linkedStack<T> &linkedStack<T>::Delete(T &x) { Node<T> *tempp = NULL; x = top->data; tempp = top->link; delete top; top = tempp; return *this; } int main() {linkedStack<int> LS; for (int i=0; i<=10;i++) { LS.Add(i*10); cout<<LS; return 0;

Topics 14.1 Introduction 14.2 Function Templates 14.3 Overloading Function Templates 14.4 Class Templates 14.5 Nontype Parameters and Default Types for Class Templates 14.6 Notes on Templates and Friends 14.7 Notes on Templates and static Members

14.7 Notes on Templates and static Members Each class-template specialization gets its own copy of the class template’s static member functions template <typename T> class A { static int x; }; template < typename T> int A<T>::x=0; A<int> a1,a2; // a1和a2共享一个x A<double> b1,b2; // b1和b2共享一个x

模板和继承的使用区别 当对象的类型不影响类中函数的行为时,就要使用模板来生成这样一组类。 当对象的类型影响类中函数的行为时,就要使用继承来得到这样一组类。

模板编译的问题 使用接口和实现分离的形式

9.4 Separating Interface from Implementation --隐藏类的源代码 类实现(成员函数定义) 类定义(接口) 类客户代码 A.cpp A.h Main.cpp 编译 编译 修改类实现代码 A.obj Main.obj 链接 EXE

模板编译的问题 错误分析: 结论:把模板的定义和实现都放到头文件中 Main.cpp 在编译目标文件是成功的,在链接的时候出现了错误。显示找不到RecT<int>类的方法。 因为其中的T类型在使用前还未知类型,如何分配内存还无法确定,因此 Rect.cpp无法独立生成目标文件。 编译模板类不能分两步走。模板类的实现文件需要和使用类的程序一起编译,编译器知道程序需要使用何种类后才可以编译出相应的类来。 结论:把模板的定义和实现都放到头文件中

Summary 函数模板和函数模板重载 类模板 定义 类型参数和非类型参数 实例创建 模板和继承 模板和友元 模板中的静态成员

Homework! 实验必选题目(交实验报告): 14.7, 14.8

14.11 What is the relationship between function templates and overloading? 函数模板与重载密切相关:(3分) 函数模板特化之间是重载关系 函数模板之间可以重载 函数模板与普通函数之间可以重载 函数模板与重载的区别:(2分) 重载是程序员编程时设计多个具有相同函数名、不同参数的函数 函数模板是在编译时,由编译器生成多个具有相同函数名、不同参数的函数模板特化

Template<typename T> class Ct1 { 习题14.20 Template<typename T> class Ct1 { friend void f1(); friend void f2(Ct1<T> &); //f2(Ct1<int> &) friend void Ct2::f3(); friend void Ct3<T>::f4(Ct1<T> &) //Ct3<int>::f4(Ct1<int> &) friend class C4; friend class Ct5<T>; //Ct5<> }