1. 程式人生 > >C++模板類與運算子作為友元函式過載

C++模板類與運算子作為友元函式過載

我自定義了一個模板類並重載了運算子,預定義實現功能為能實現對陣列一般操作,類似於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 &)" (
[email protected]
[email protected][email protected]@[email protected]@@[email protected]@[email protected][email protected]@@@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;
}


執行截圖




第二種方法

#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++模板運算子作為函式過載

我自定義了一個模板類並重載了運算子,預定義實現功能為能實現對陣列一般操作,類似於vector。 #ifndef ARRAY_H #define ARRAY_H #include <iostream> using namespace std; templa

成員函式過載運算子函式過載運算子的比較

下面的例子可以很好的說明定義為friend   function的好處.      #include   <iostream.h>      class   point      {              int   x;              int   y;             

C++模板Qt信號槽混用

tar com get 信號 obi template blog blank emp 參考:https://www.cnblogs.com/csuftzzk/p/qt_mix_with_template.html http://mobile.51cto.com/symbia

C++運算子過載函式過載

實驗要求: 1、設計一個類,用自己的成員函式過載運算子,使對整型的運算子=、+、-、*、/ 適用於分數運算。要求: (1)輸出結果是最簡分數(可以是帶分數); (2)分母為1,只輸出分子。 #include<iostream> using

C++過載(2):通過成員函式函式過載

分別通過成員函式和友元函式完成過載 #include <iostream> using namespace std; class Complex { public: Complex(double real =0,double imag=0):real(real),imag(i

過載運算子以及函式

在自己已經創造好的類中如果想更加簡化一些運算,比如之前兩個類中的物件如果想要相加必須通過類成員函式來實現,現在假設之前建立好的time類中的兩個物件 time a; time b; timec; c=a+b; 如果想實現上述運算,就要求過載運算子:利用關鍵字operator

C++ 模板中的static變數和函式 初始化

關鍵詞: C++ 模板 static 變數 函式  初始化 這篇文章主要介紹關於模板類中如果有static變數如何初始化問題。 重要:如果不初始化static變數,那麼編譯可能沒有問題,但是程式有問題,可能編譯有問題,但是不能確定是初始化問題。 #include"ios

函式過載操作符

當使用namespace std的時候會出現訪問不了私有成員的錯誤,不使用std便沒有錯誤。奇怪的是之前的程式使用的std也沒有錯誤,不知為何  #ifndef STRING_H_ #define STRING_H_ #include <iostream> //

c/c++ 模板STL小例子系列<二> 模板函數

vat stream col ons cout include ios ring 沒有 c/c++ 模板與STL小例子系列<二> 模板類與友元函數 比如某個類是個模板類D,有個需求是需要重載D的operator<<函數,這時就需要用到友元。 實現這樣

C++】C++的學習(三)——運算子過載函式

前言       前面的兩篇博文中介紹了類的一些基本特性,今天講一講運算子過載和友元。運算子過載      運算子過載是C++中一種形式的多型,運算子過載將過載的概念運用到運算子上,賦予運算子更多地含義。也許乍然一聽,似乎我們對它並不熟悉,其實它一直為我們使用,例如 * 運算

運算子過載函式作為成員函式函式的區別

運算子過載函式作為類成員函式與友元函式 最近在學習C++的基礎,簡單地記一些筆記。 關於運算子過載函式作為成員函式還是友元函式的注意點: 當運算子過載函式作為類的成員函式時,要求運算元左邊必須是一個物件,而函式的引數可以是同類的物件也可以是普通的變數

學生,含學生姓名成績,用函式訪問私有成員,對兩個物件的成績進行比較。(2018.9.19 c++作業)

定義兩個物件,與一個友元函式(使用c++中引用傳遞的方式,實現引數的傳遞) #include using namespace std; class student { private: char name[20]; float grade; public: s

關於模板函式的宣告定義

//Widget.h #ifndef _WIDGET_H_ #define _WIDGET_H_ #include <iostream> using namespace std; template<class T> class Widget {

C++模板中的宣告

對於在一個類中宣告一個函式或者一個類的友元,我們應該是十分熟悉了,但是這兩天在做題的時候遇到一個問題,就是如何在一個類模板中宣告一個模板函式與我們的模板類的友元關係? 剛開始遇到這個問題的時候,說實話我有點懵,因為之前根本沒考慮到這一層,所以趁這次機會又將模板和友元相關的東

C++ 運算子過載函式的簡單運用例項

前言:C++的運算子過載與友元函式是像類似Java這種純的面向物件程式語言所不具備的特徵,那麼使用運算子過載與友元函式到底能帶來什麼樣的不同呢? 舉個例子,假如需要實現一個複數的加減法,用Java實現後兩個複數相加的程式碼可能如下: public sta

C++實現輸入輸出運算子過載函式和成員函式實現複數Complex

今天答應幫朋友做一個C++題目,頗費了一番周折,終於還是寫出來了,讓很久沒敲程式碼的我反省了一下,也回憶了以前學過的知識。 題目要求如下: 一、按下列要求編制複數類,並除錯通過: 1)  基本的建構函式; 2)  成員運算子+、-實現複數的加減運算; 3)  友元運算子+

C++ 過載運算子 函式作為過載運算子 過載運算子+

以友元函式作為過載運算子的方式過載運算子+ 下面的例子來自於課本 #include <iostream> using namespace std; class Complex {

C++模板中的函式的宣告和定義分別放在哪裡

        前面提到了模板的宣告和定義推薦都放在標頭檔案中,那麼該類中的友元函式的宣告和定義該放在哪裡呢?         因為友元函式並不屬於這個類, 按照習慣,我們一般把宣告放在類中,而把定義放在類的外面。但對於類模板來說,這樣就出問題了。很多編譯器並不支援將友元函

模板函式

模板的友元可以分為三類: 非模板友元約束模板友元,即友元的型別取決於類被例項化時的型別非約束模板友元,即友元的所有具體化都是類的每一個具體化的友元 1. 模板類的非模板友元,即該友元函式不存在模板,但是該友元函式聲明於一個模板類中。 圖1 如果沒有需要模板類引數,這與

C++學習筆記(10)運算子過載函式

c++允許我們為運算子定義專門的函式,這被稱為運算子過載: 運算子可以簡化字串的操作,‘+’,以及使用關係運算符比較字串,[ ]運算子訪問向量中的元素; 例如: #include <iostream> #include <string> #include <