学习C++时,有时候我们会使用微软提供的VS软件,在学习到模板类重载左移操作符时会遇到一些问题,下面写一个简单的程序来举例:
#include <iostream>
using namespace std;
template<class T>
class Complex
{
private:
T a;
public:
Complex(T a);
friend ostream & operator<< <T>(ostream & os, const Complex<T> & obj); //VS中特殊的标志<T>
};
template<class T>
Complex<T>::Complex(T a)
{
this->a = a;
}
template<class T>
ostream & operator<<(ostream & os, const Complex<T> & obj)
{
os << "a = " << obj.a;
return os;
}
int main(int argc, char const *argv[])
{
Complex<int> c1(4);
cout << c1 << endl;
system("pause");
return 0;
}
该程序只是VS2010中写入的程序,为了方便,我将这些程序我都是写到一个文件中,如果要将类的声明和类的实现,还有主函数的实现分成三个文件,则必须在主函数中包含的是类的实现的文件,即:
模板类的声明在a.h中,类的实现在a.cpp中,主函数在main.cpp中,则main.cpp中必须包含#include "a.cpp"而不能是"a.h"头文件,这只是一个小细节,在Linux环境下同样适用。
上面程序中重载<<操作符时在声明的部分加入了<T>才能使模板类编译通过,这与VS编译器的实现有关,而且在写<<操作符的实现时不能再写<T>。
这个同样的程序在Linux下不能运行,因为Linux使用的是g++编译器,g++编译器的编译原理与VS的编译器编译原理不同。在Linux中,程序应该这样写:
#include <iostream>
using namespace std;
template<class T>
class Complex
{
private:
T a;
public:
Complex(T a);
template<class Mytype>
friend ostream & operator<<(ostream & os, const Complex<Mytype> & obj);//在使用g++编译器中需要加上类的的前置声明
};
template<class T>
Complex<T>::Complex(T a)
{
this->a = a;
}
template<class T>
ostream & operator<<(ostream & os, const Complex<T> & obj)
{
os << "a = " << obj.a;
return os;
}
/*
template<class Mytype>
ostream & operator<<(ostream & os, const Complex<Mytype> & obj)
{
obj.count++;
os << "count = " << obj.count << endl;
os << "a = " << obj.c_a;
return os;
}
*/
int main(int argc, char const *argv[])
{
Complex<int> c1(8);
cout << c1 << endl;
return 0;
}
这是在Linux下使用g++编译器时写的代码,其中我还在网上查阅的另外一种在operator<<(...)中间加上<>即:operator<< <>(...)这种方法不能再g++编译器中编译通过。
g++中左移操作符在声明的时候需要加上类的模板函数声明,且该声明的类型不能和类的声明类型相同,即程序中使用了Mytype声明友元函数左移操作符,在实现中既可以使用Mytype类型实现,也可以使用T类型标志来实现左移操作符的重载,这里选择和类的声明标志相同。