和类一样,类模板里面声明的函数,其函数体写在类里面和外面都行,但是有一点需要注意:1.用友元函数重载<< 或 >>运算符,函数声明写在类模板里面,函数实现写在类模板外面,要在函数名和函数输入参数之间写上Typename定义的那个类型,如template <typename T>,则应写上<T>。举个例子,如果重载运算符<<,且重载函数的函数体写在类模板的外面,则在类模板里面声明重载函数时,函数声明应该写成ostream operator<< <T> (ostream&,类模板名<T>&)。

上面这个知识点是很多新手易犯的错误,很多人在网上跪求原因,一定要注意!

2.一般性的友元函数,函数声明写在类模板里面,函数实现写在类模板外面,需要在类的前面添加函数的前置声明,否则编译肯定通不过。因为这个方法比较复杂,所以碰到类模板的时候,能不用友元函数尽量不要用友元函数。

在类的前面添加前置函数声明的方法如下:

1)template <Typename T>

class Complex //这里假定类模板的名字就是Complex,这句话是类的前置声明

template <Typename T>

Complex<T> myfun(class<T>& ,class<T>&) //函数的前置声明

2)在类模板的内部声明应写成:friend Complex myfun<T>(Complex& ,Complex&) ,这里必须要加<T>

3)友元函数在类模板外面的实现写成:

Complex<T> myfun(class<T>& c1 ,class<T>& c2)

{...}

4)友元函数的调用写成:myfun<int>(c1,c2),这里<int>也是必须要加的

究其原因,与C++编译器对类模板的二次编译有关。当C++编译器遇到类模板里面的函数声明时,生成一个函数头;遇到类模板外面的函数体实现时,又生成了一个函数头。因为友元函数是全局函数,它不属于类模板,所以两次生成的函数头不一样,导致了C++编译器找不到由原函数的函数体实现了,所以编译就会报错。而且不同的编译器,可能有的支持这个语法,有的不支持这个语法,所以碰到函数模板时一定要谨慎使用友元函数,能不用就不要用。

下面是具体实例:

 1 #include <iostream>
 2
 3 using namespace std;
 4
 5 /*
 6 //1.类模板的函数都写在类的内部
 7 template <typename T>
 8 class Complex
 9 {
10     friend ostream& operator<<(ostream& out,Complex& c)
11     {
12         out<<c.a<<"+"<<c.b<<"i";
13         return out;
14     }
15
16 public:
17     Complex(T a,T b)
18     {
19         this->a=a;
20         this->b=b;
21     }
22
23     Complex operator+(Complex& c)
24     {
25         Complex temp(this->a+c.a,this->b+c.b);
26         return temp;
27     }
28
29     void printCom()
30     {
31         cout<<this->a<<"+"<<this->b<<"i"<<endl;
32     }
33
34 private:
35     T a;
36     T b;
37 };
38 */
39
40 //2.类模板的函数都写在类的外部
41 template <typename T>
42 class Complex
43 {
44     //注意,友元函数在类模板的类体里面声明的时候,在函数的名字和函数参数类型之间加了一个<T>,若不加这个<T>,则编译通不过!
45     friend ostream& operator<<<T>(ostream& out,Complex& c);
46
47 public:
48     Complex(T,T);//构造函数
49     Complex operator+(Complex& );//重载“+”操作符
50     void printCom();//普通函数
51
52 private:
53     T a;
54     T b;
55 };
56
57 //注意友元函数在类体里面的声明的写法!
58 template <typename T>
59 ostream& operator<<(ostream& out,Complex<T>& c)
60 {
61     out<<c.a<<"+"<<c.b<<"i";
62     return out;
63 }
64
65 template <typename T>
66 Complex<T>::Complex(T a,T b)
67 {
68     this->a=a;
69     this->b=b;
70 }
71
72 template <typename T>
73 Complex<T> Complex<T>::operator+(Complex<T>& c)
74 {
75     Complex<T> temp(this->a+c.a,this->b+c.b);
76     return temp;
77 }
78
79 template <typename T>
80 void Complex<T>::printCom()
81 {
82     cout<<this->a<<"+"<<this->b<<"i"<<endl;
83 }
84
85 int main()
86 {
87     Complex<float> c1(1.2,2.5),c2(3.2,5.3);
88
89     c1.printCom();
90     c2.printCom();
91
92     cout<<c1+c2<<endl;
93
94     return 0;
95 }

转载于:https://www.cnblogs.com/jswu-ustc/p/8514434.html

类模板里面的函数写在类模板里面和写在类模板的外面,且在1个.cpp文件中相关推荐

  1. 将类的定义放在头文件中,把成员函数的实现代码放在一个cpp文件中

    将类的定义放在头文件中,把成员函数的实现代码放在一个cpp文件中 写这种.h和.cpp文件分开的大程序,虽然对很多人来说很简单,对自己来说算是第一次吧,好好学C++,加油~ 题目:定义Point类,由 ...

  2. boost::regex模块在 cpp 文件中搜索类定义,使用绑定成员函数回调测试程序

    boost::regex模块在 cpp 文件中搜索类定义,使用绑定成员函数回调测试程序 实现功能 C++实现代码 实现功能 boost::regex模块在 cpp 文件中搜索类定义,使用绑定成员函数回 ...

  3. boost::regex模块在 cpp 文件中搜索类定义,使用全局回调函数的测试程序

    boost::regex模块在 cpp 文件中搜索类定义,使用全局回调函数的测试程序 实现功能 C++实现代码 实现功能 boost::regex模块在 cpp 文件中搜索类定义,使用全局回调函数的测 ...

  4. boost::regex模块在 cpp 文件中搜索类定义,使用全局数据的测试程序

    boost::regex模块在 cpp 文件中搜索类定义,使用全局数据的测试程序 实现功能 C++实现代码 实现功能 boost::regex模块在 cpp 文件中搜索类定义,使用全局数据的测试程序 ...

  5. boost::regex模块在 cpp 文件中搜索类定义,使用 C++ Builder 闭包作为回调的测试程序

    boost::regex模块在 cpp 文件中搜索类定义,使用 C++ Builder 闭包作为回调的测试程序 实现功能 C++实现代码 实现功能 boost::regex模块在 cpp 文件中搜索类 ...

  6. boost::regex模块实现在 cpp 文件中搜索类定义的测试程序

    boost::regex模块实现在 cpp 文件中搜索类定义的测试程序 实现功能 C++实现代码 实现功能 boost::regex模块实现在 cpp 文件中搜索类定义的测试程序 C++实现代码 #i ...

  7. C++ 在一个cpp文件中使用另一个cpp文件中定义的函数

    C++ 在一个cpp文件中 使用另一个cpp文件中定义的函数 建立一个console项目 头文件 cpp文件 main.cpp 建立一个console项目 以dev为例,在[文件][新建][项目],新 ...

  8. abstract类中不可以有private的成员_C++ 类:声明成员函数与实现

    接上文... 16.3类的成员 2.成员函数 1.构造函数 ... 2.拷贝构造函数 有了类的构造函数我们就可以创建类的实例了,下图中分别使用不同的构造函数一共创建了4个动物的对象,现在程序中就有4个 ...

  9. C++:运算符重载与类的赋值运算符重载函数

    目录 章节知识架构 一.运算符重载 1. 运算符重载的基本概念 代码段1 2.关于运算符重载的重要语法细则 二.运算符重载在类中的使用 三.类的默认成员函数:=重载函数(赋值运算符重载) 1.自定义= ...

最新文章

  1. Facebook 开源了一整套重要的 Linux 内核组件与工具!
  2. 表格单元格中的CSS文本溢出?
  3. linux pfn,ARM Linux下的page和pfn之间转换的宏。
  4. access开发精要(3)-子数据表
  5. uniapp 页面下次渲染完成后执行:this.$nextTick
  6. C/C++学习之路: 多态
  7. SQL Server 无法生成 FRunCM 线程。请查看 SQL Server 错误日志和 Windows 事件日志(转)...
  8. linux中安装jdk安装(rpm安装)
  9. fineuploader php服务端
  10. opencv4版本和3版本_Spring Boot 太狠了,一口气发布了 3 个版本!
  11. Oracle中表pagesize,Oracle使用pagesize命令
  12. 扁平化设计的流行配色方案
  13. m低信噪比下GPS信号的捕获算法研究,使用matlab算法进行仿真
  14. FANUC机器人示教时遇到奇异点的解决办法
  15. 计算机主板别称是什么城,武汉别名江城又称什么城 武汉被誉为什么城之称
  16. graylog+kafka+zookeeper(单机测试及源码),graylog测试用例及源码(三)
  17. 常用标点符号的英文名称
  18. Camera基本结构及原理
  19. 最长递增子序列的O(NlogN)算法
  20. 微信点开分享文章所带的关键字

热门文章

  1. SSH框架之Maven
  2. 中国信息化系统集成行业协会:计算机系统集成行业还有发展空间么?
  3. java oj题及答案_华为OJ答案(java版)题目2
  4. UE4学习笔记:学习UE4中的UMG(图形UI设计器)工具(四):UMG中的动画
  5. Euler-Maruyama 方法数值算例
  6. Windows安装DB2
  7. 使用 SAP WebIDE 开发 SAP Fiori Worklist 应用消费 OData 服务
  8. 大数据时代,人流量统计系统如何提高商业价值
  9. 数据结构背包问题c语言思路,C语言学习趣事_数据结构_经典命题_1_背包问题_分析_1...
  10. Mac下不用虚拟机一样可以使用PLSQL Developer