1.所有的类模板函数都写在类的内部,在一个cpp中
#include<iostream> using namespace std; template<typename T> class Complaex { friend ostream& operator<<(ostream& out, Complaex& c3)//引用支持链式编程 { out << c3.a << "+" << c3.b << "i"<< endl; return out; } public: Complaex(T a ,T b) { this->a = a; this->b = b; } Complaex operator+(Complaex& c2) { Complaex temp(a + c2.a, b + c2.b); return temp; } void printCom() { cout << "a: " << a << " b: " << b << endl; } protected: T a; T b; }; //运算符<< 和 >> 重载只能用友元函数,其他操作符重载都用成员函数,不要滥用友元函数 //ostream &operator<<(ostream &out, Complaex &c3) //{ // out << "a: " << c3.a << " b: " << c3.b << endl; // return out; //} int main() { Complaex<int>c1(1, 2);//需要把模板类进行具体化之后才能定义对象 C++要分配内存 Complaex<int>c2(3, 4); Complaex<int>c3 = c1 + c2; //Complaex operator+(Complaex &c2); cout << c3 << endl; /* ostream &operator<<(ostream & out, Complaex & c3)*/; system("pause"); return 0; }
2.所有类模板函数都写在类的外部,并且都在一个cpp文件里面
在将有源函数放在cpp外部时报错:
严重性 代码 说明 项目 文件 行 禁止显示状态
错误 LNK2019 无法解析的外部符号 "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl operator<<(class std::basic_ostream<char,struct std::char_traits<char> > &,
class Complaex<int> &)" (??6@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@AAV?$Complaex@H@@@Z),
函数 _main 中引用了该符号 类模板 C:vslearn类模板demo08_所有函数都写在类的外部,在一个cpp里面.obj 1
根据网上教程在operat<<后加<T>编译器会认为<<<T>使编译时两个函数头相同。
但是在编译器认为,此时<<<T>是一个整体操作运算符,在页面上提示问题,但是编译后不会出现问题,可能是编译器和vs之间不协调的地方。
代码:
#include<iostream> using namespace std; template<typename T> class Complaex { friend ostream& operator<< <T> (ostream& out, Complaex& c3);//引用支持链式编程 public: Complaex(T a, T b); Complaex operator+(Complaex& c2); void printCom(); protected: T a; T b; }; template<typename T> //构造函数的实现写在了类的外面 Complaex<T>::Complaex(T a, T b) { this->a = a; this->b = b; } template<typename T> void Complaex<T>::printCom() { cout << "a: " << a << " b: " << b << endl; } //成员函数运算符重载 template<typename T> Complaex<T> Complaex<T>::operator+(Complaex<T>& c2)//函数参数需要具体化一个类 参数也需要具体化一个类 { Complaex temp(a + c2.a, b + c2.b); return temp; } //友元函数左移<<实现运算符重载 template<typename T> //本质是模板是两次编译生成的 第一次生成的函数头和第二次生成的函数头不一样。 ostream& operator<< (ostream& out, Complaex<T>& c3)//引用支持链式编程 { out << c3.a << "+" << c3.b << "i" << endl; return out; } int main() { Complaex<int>c1(1, 2);//需要把模板类进行具体化之后才能定义对象 C++要分配内存 Complaex<int>c2(3, 4); Complaex<int>c3 = c1 + c2; //Complaex operator+(Complaex &c2); cout << c3 << endl; /* ostream &operator<<(ostream & out, Complaex & c3)*/; system("pause"); return 0; }
3.所有的类模板函数写在类的外部,在不同的.h和.cpp中
首先要创建.h和.cpp文件,然后在里面申明。
.h:
#pragma once #include<iostream> using namespace std; template<typename T> class Complaex { friend ostream& operator<< <T> (ostream& out, Complaex& c3);//引用支持链式编程 public: Complaex(T a, T b); Complaex operator+(Complaex& c2); void printCom(); protected: T a; T b; };
.cpp:
#include<iostream> using namespace std; #include"complex.h" template<typename T> //构造函数的实现写在了类的外面 Complaex<T>::Complaex(T a, T b) { this->a = a; this->b = b; } template<typename T> void Complaex<T>::printCom() { cout << "a: " << a << " b: " << b << endl; } //成员函数运算符重载 template<typename T> Complaex<T> Complaex<T>::operator+(Complaex<T>& c2)//函数参数需要具体化一个类 参数也需要具体化一个类 { Complaex temp(a + c2.a, b + c2.b); return temp; } //友元函数左移<<实现运算符重载 template<typename T> //本质是模板是两次编译生成的 第一次生成的函数头和第二次生成的函数头不一样。 ostream& operator<< (ostream& out, Complaex<T>& c3)//引用支持链式编程 { out << c3.a << "+" << c3.b << "i" << endl; return out; }
#include<iostream> #include"complex.cpp" using namespace std; int main() { Complaex<int>c1(1, 2);//需要把模板类进行具体化之后才能定义对象 C++要分配内存 Complaex<int>c2(3, 4); Complaex<int>c3 = c1 + c2; //Complaex operator+(Complaex &c2); cout << c3 << endl; /* ostream &operator<<(ostream & out, Complaex & c3)*/; system("pause"); return 0; }