C++模板类与运算符作为友元函数重载

时间:2022-10-17 17:38:07

我自定义了一个模板类并重载了运算符,预定义实现功能为能实现对数组一般操作,类似于vector。

#ifndef ARRAY_H
#define ARRAY_H

#include <iostream>
using namespace std;


template<class T>
class Array{
friend ostream& operator<<(ostream&, const Array &);
friend istream& operator>>(istream&, Array &);
public:
Array(int arraySize = 10){
size = (arraySize > 0 ? arraySize : 10);
ptr = new T[size];
for (int i = 0; i < size; i++)
ptr[i] = 0;

}
Array(const Array &arrayToCopy){
ptr = new int[size];

for (int i = 0; i < size; i++){
ptr[i] = arrayToCopy[i];
}
}



~Array(){
delete[] ptr;
}

int getSize()const{
return size;
}

const Array& operator=(const Array &right){
if (&right != this){
if (size != right.size){
delete[] ptr;
size = right.size;
ptr = new T[size];
}
for (int i = 0; i < size; i++)
ptr[i] = right.ptr[i];
}
return *this;
}

bool operator==(const Array &right)const{
if (size != right.size)
return false;

for (int i = 0; i < size; i++)
if (ptr[i] != right.ptr[i])
return false;

return true;
}

bool operator!=(const Array &right)const{
return !(*this == right);
}


T& operator[](int subscript)
{
if (subscript < 0 || subscript >= size){
cerr << "\nError: Subscript " << subscript
<< "out of range" << endl;
exit(1);
}

return ptr[subscript];
}
T operator[](int subscript)const{
if (subscript < 0 || subscript >= size)
{
cerr << "\nError: Subscript" << subscript
<< "out of range" << endl;
exit(1);
}
return ptr[subscript];
}

private:
int size;
T *ptr;
};



#endif




template<class T>
istream& operator>>(istream &input, Array<T> &a){
for (int i = 0; i < a.size; i++)
input >> a.ptr[i];
return input;
}

template<class T>
ostream& operator<<(ostream &output, const Array<T> &a){
int i;

for (i = 0; i < a.size; i++){
output << setw(12) << a.ptr[i];

if ((i + 1) % 4 == 0)
ouput << endl;
}

if (i % 4 != 0)
output << endl;

return output;
}
#include <iostream>#include "Array.h"using namespace std;int main(){Array<int> integers1(7);cout << "Size of Array integers1 is "<< integers1.getSize()<< "\nArray after initialization:\n"<< integers1;}
出错错误原因为

1>main.obj : error LNK2019: 无法解析的外部符号 "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl operator<<(class std::basic_ostream<char,struct std::char_traits<char> > &,class Array<int> const &)" (??6@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@ABV?$Array@H@@@Z),该符号在函数 _main 中被引用

我猜测的原因是cin为ostream对象实例,但是没对我自定义的类型进行<<重载。不知道我的猜测对不对,希望有经验的人给我点文档与链接。


问题已经得到解决,

模板类中的友元函数需要进行特别的处理。原因请参考我的博文

http://blog.csdn.net/u010003835/article/details/47312955


设置友元后

头文件

#ifndef ARRAY_H
#define ARRAY_H

#include <iostream>
#include <iomanip>
using namespace std;


//模板类前置声明
template<class T>
class Array;



//Array模板类的友元声明
template<class T>
istream& operator>>(istream& input, Array<T>& a);
template<class T>
ostream& operator<<(ostream& output, const Array<T>& a);


template<class T>
class Array{
friend ostream& operator<< <> (ostream&, const Array<T>&);
friend istream& operator>> <> (istream&, Array<T>&);
public:
Array(int arraySize = 10){
size = (arraySize > 0 ? arraySize : 10);
ptr = new T[size];
for (int i = 0; i < size; i++)
ptr[i] = 0;

}
Array(const Array &arrayToCopy){
ptr = new int[size];

for (int i = 0; i < size; i++){
ptr[i] = arrayToCopy[i];
}
}



~Array(){
delete[] ptr;
}

int getSize()const{
return size;
}

const Array& operator=(const Array &right){
if (&right != this){
if (size != right.size){
delete[] ptr;
size = right.size;
ptr = new T[size];
}
for (int i = 0; i < size; i++)
ptr[i] = right.ptr[i];
}
return *this;
}

bool operator==(const Array &right)const{
if (size != right.size)
return false;

for (int i = 0; i < size; i++)
if (ptr[i] != right.ptr[i])
return false;

return true;
}

bool operator!=(const Array &right)const{
return !(*this == right);
}


T& operator[](int subscript)
{
if (subscript < 0 || subscript >= size){
cerr << "\nError: Subscript " << subscript
<< "out of range" << endl;
exit(1);
}

return ptr[subscript];
}
T operator[](int subscript)const{
if (subscript < 0 || subscript >= size)
{
cerr << "\nError: Subscript" << subscript
<< "out of range" << endl;
exit(1);
}
return ptr[subscript];
}

private:
int size;
T *ptr;
};



#endif




template<class T>
istream& operator>>(istream &input, Array<T> &a){
for (int i = 0; i < a.size; i++)
input >> a.ptr[i];
return input;
}

template<class T>
ostream& operator<<(ostream &output, const Array<T> &a){
int i;

for (i = 0; i < a.size; i++){
output << setw(12) << a.ptr[i];

if ((i + 1) % 4 == 0)
output << endl;
}

if (i % 4 != 0)
output << endl;

return output;
}

正确的写法就是代码段中的写法。<>也必不可少,其实<>有两

重意思:


一是,表明此友元函数是函数模板;


二是,此模板使用的模板类型参数为当前

模板类的类型参数class。


主函数
<pre name="code" class="cpp">#include "Array.h"using namespace std;int main(){Array<int> integers1(7);Array<int> integers2;Array<char> char_string(100);cout << "Size of Array integers1 is "<< integers1.getSize()<< "\nArray after initialization:\n" << integers1 << endl;cout << "Size of Array char_string is "<< char_string.getSize()<< "\nArray after initialization:\n" << endl;if (integers1 != integers2)cout << "integers1 and integers2 are not equal" << endl;cout << "\ninteger2[5] is " << integers2[5] << endl;}


 
运行截图
C++模板类与运算符作为友元函数重载



第二种方法

#ifndef ARRAY_H
#define ARRAY_H

#include <iostream>
#include <iomanip>
using namespace std;



//模板类前置声明
template<class T>
class Array;




//Array模板类的友元声明
template<class S>
istream& operator>>(istream& input, Array<S>& a);
template<class S>
ostream& operator<<(ostream& output, const Array<S>& a);


template<class T>
class Array{
template<class S>
friend ostream& operator<<(ostream&, const Array<S>&);

template<class S>
friend istream& operator>>(istream&, Array<S>&);
public:
Array(int arraySize = 10){
size = (arraySize > 0 ? arraySize : 10);
ptr = new T[size];
for (int i = 0; i < size; i++)
ptr[i] = 0;

}
Array(const Array &arrayToCopy){
ptr = new int[size];

for (int i = 0; i < size; i++){
ptr[i] = arrayToCopy[i];
}
}



~Array(){
delete[] ptr;
}

int getSize()const{
return size;
}

const Array& operator=(const Array &right){
if (&right != this){
if (size != right.size){
delete[] ptr;
size = right.size;
ptr = new T[size];
}
for (int i = 0; i < size; i++)
ptr[i] = right.ptr[i];
}
return *this;
}

bool operator==(const Array &right)const{
if (size != right.size)
return false;

for (int i = 0; i < size; i++)
if (ptr[i] != right.ptr[i])
return false;

return true;
}

bool operator!=(const Array &right)const{
return !(*this == right);
}


T& operator[](int subscript)
{
if (subscript < 0 || subscript >= size){
cerr << "\nError: Subscript " << subscript
<< "out of range" << endl;
exit(1);
}

return ptr[subscript];
}
T operator[](int subscript)const{
if (subscript < 0 || subscript >= size)
{
cerr << "\nError: Subscript" << subscript
<< "out of range" << endl;
exit(1);
}
return ptr[subscript];
}

private:
int size;
T *ptr;
};



#endif




template<class T>
istream& operator>>(istream &input, Array<T> &a){
for (int i = 0; i < a.size; i++)
input >> a.ptr[i];
return input;
}

template<class T>
ostream& operator<<(ostream &output, const Array<T> &a){
int i;

for (i = 0; i < a.size; i++){
output << setw(12) << a.ptr[i];

if ((i + 1) % 4 == 0)
output << endl;
}

if (i % 4 != 0)
output << endl;

return output;
}

C++模板类与运算符作为友元函数重载