国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

C++提高編程——模板

這篇具有很好參考價值的文章主要介紹了C++提高編程——模板。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

C++提高編程

本階段主要針對C++泛型編程STT技術(shù)做詳細講解,探討C++更深層的使用

1模板

1.1模板的概念

模板就是建立通用的模具,大大提高復用性

例如生活中的模板

寸照片模板:

1.2函數(shù)模板

  1. C++另一種編程思想稱為 泛型編程,主要利用的技術(shù)就是模板
  2. C++提供兩種模板機制:函數(shù)模板和類模板

1.2.1函數(shù)模板語法

函數(shù)模板作用:

建立一個通用函數(shù),其函數(shù)返回值類型和形參類型可以不具體制定,用一個虛擬的類型來代表。

語法:

//函數(shù)聲明或定義

template<typename T>

解釋:

  1. template —— 聲明創(chuàng)建模板
  2. typename —— 表面其后面的符號是一種數(shù)據(jù)類型,可以用class代替
  3. T —— 通用的數(shù)據(jù)類型,名稱可以替換,通常為大寫字母
#include<iostream>;
using namespace std;
//兩個整型交換函數(shù)
void swapInt(int &a, int &b)
{
	int temp = a;
	a = b;
	b = temp;
}
//函數(shù)模板
template<typename T>//聲明一個模板,告訴編譯器后面代碼中緊跟著的T不要報錯,T是一個通用數(shù)據(jù)類型。
void mySwap(T& a, T& b)
{
	T temp = a;
	a = b;
	b = temp;
}
//交換兩個浮點型函數(shù)
void swapDouble(double& a, double& b)
{
	double temp = a;
	a = b;
	b = temp;
}
//測試
void test01()
{
	int a = 10;
	int b = 20;
	/*swapInt(a,b);*/
	//利用函數(shù)模板交換
	//兩種方式使用函數(shù)模板
	//1、自動類型推導
	//mySwap(a,b);
	//2、顯示指定類型
	mySwap<int>(a, b);
	cout << "a=" << a << endl;
	cout << "b=" << b << endl;

	//double c = 1.1;
	//double d = 2.2;
	//swapDouble(c, d);
	//cout << "c=" << c << endl;
	//cout << "d=" << d << endl;
}
//函數(shù)模板
int main()
{
	test01();

	system("pause");//按任意鍵繼續(xù)
	return 0;  
}

總結(jié):

  1. 函數(shù)模板利用關(guān)鍵字 template
  2. 使用函數(shù)模板有兩種方式:自動類型推導、顯示指定類型
  3. 模板的目的是為了提高復用性,將類型參數(shù)化

1.2.2函數(shù)模板注意事項

注意事項:

  1. 自動類型推導,必須推導出---致的數(shù)據(jù)類型T,才可以使用
  2. 模板必須要確定出T的數(shù)據(jù)類型,才可以使用
#include<iostream>;
using namespace std;
//函數(shù)模板注意事項
template<typename T>//typename可以替換class
void mySwap(T&a, T&b)
{
	T temp = a;
	a = b;
	b = temp;
}
//1、自動類型推導,必須推導出一致的數(shù)據(jù)類型T才可以使用。
void test01()
{
	int a = 10;
	int b = 20;
	char c = 'c';
	mySwap(a, b);//正確
	//mySwap(a, c);//錯誤?。?!推導不出一致的T類型。
	cout << "a=" << a << endl;
	cout << "b=" << b << endl;
}
//2、模板必須要確定出T的數(shù)據(jù)類型,才可以使用。
template<typename T>//typename可以替換class
void func()
{
	cout << "func 調(diào)用" << endl;
}
void test02()
{
	func<int>();
}
//主函數(shù)
int main()
{
	test01();
	test02();

	system("pause");//按任意鍵繼續(xù)
	return 0;
}

總結(jié)

使用模板時必須確定出通用數(shù)據(jù)類型T,并且能夠推導出一致的類型

1.2.3函數(shù)模板案例

案例描述:

  1. 利用函數(shù)模板封裝一個排序的函數(shù),可以對不同數(shù)據(jù)類型數(shù)組進行排序
  2. 排序規(guī)則從大到小,排序算法為選擇排序
  3. 分別利用char數(shù)組int數(shù)組進行測試
#include<iostream>;
using namespace std;
//實現(xiàn)通用 對數(shù)組進行排序的函數(shù)
//規(guī)則  從大到小
//算法 選擇
//測試 char 數(shù)組、int數(shù)組

//交換函數(shù)模板
template<typename T>
void mySawp(T& a, T& b)
{
	T temp = a;
	a = b;
	b = temp;
}
//排序算法
template<typename T>
void mySort(T arr[],int len)
{
	for (int i = 0; i < len; i++)
	{
		//認定的最大值 比 遍歷出的數(shù)值 要小,說明j下標的元素才是真正的最大值
		int max = i;//認定最大值的下標
		for (int j = i + 1; j < len; j++)
		{
			if (arr[max] < arr[j])
			{
				max = j;//更新最大值下標
			}
		}
		if (max != i)
		{
			//交換max和i元素
			mySawp(arr[max], arr[i]);
		}
	}
}
//打印數(shù)組的模板
template<typename T>
void printArray(T arr[], int len)
{
	for (int i = 0; i < len; i++)
	{
		cout << arr[i] << " ";	
	}
	cout << endl;
}
//測試
void test01()
{
	//測試char數(shù)組
	char charArr[] = "badcfe";
	int num = sizeof(charArr) / sizeof(char);
	mySort(charArr, num);
	printArray(charArr, num);
}
void test02()
{
	//測試int數(shù)組
	int intArr[] = {7,5,1,3,9,2,4,6,8};
	int num = sizeof(intArr) / sizeof(int);
	mySort(intArr, num);
	printArray(intArr, num);
}

int main()
{
	test01();
	test02();

	system("pause");//按任意鍵繼續(xù)
	return 0;
}

1.2.4 普通函數(shù)與函數(shù)模板的區(qū)別

普通函數(shù)與函數(shù)模板區(qū)別:

  1. 普通函數(shù)調(diào)用時可以發(fā)生自動類型轉(zhuǎn)換 (隱式類型轉(zhuǎn)換)
  2. 函數(shù)模板調(diào)用時,如果利用自動類型推導,不會發(fā)生隱式類型轉(zhuǎn)換
  3. 如果利用顯示指定類型的方式,可以發(fā)生隱式類型轉(zhuǎn)換
#include<iostream>;
using namespace std;
//普通函數(shù)與函數(shù)模板區(qū)別:
//1、普通函數(shù)調(diào)用可以發(fā)生隱式類型轉(zhuǎn)換
//2、函數(shù)模板 用自動類型推導,不可以發(fā)生隱式類型轉(zhuǎn)換
//3、函數(shù)模板 用顯示指定類型,可以發(fā)生隱式類型轉(zhuǎn)換

//普通函數(shù)
int myAdd01(int a, int b)
{
	return a + b;
}
//函數(shù)模板
template<typename T>
T myAdd02(T a, T b)
{
	return a + b;
}

void test01()
{
	int a = 10;
	int b = 20;
	char c = 'c';//a——97  c——99;
	cout << myAdd01(a, b) << endl;
	cout << myAdd01(a, c) << endl;

	//自動類型推導 不會發(fā)生隱式類型轉(zhuǎn)換
	cout << myAdd02(a, b) << endl;
	//cout << myAdd02(a, c) << endl;//錯誤!!!

	//顯示指定類型 會發(fā)生隱式類型轉(zhuǎn)換
	cout << myAdd02<int>(a, c) << endl;
}

int main()
{
	test01();

	system("pause");//按任意鍵繼續(xù)
	return 0;
}

總結(jié): 建議使用顯示指定類型的方式,調(diào)用函數(shù)模板,因為可以自己確定通用類型T。

1.2.5 普通函數(shù)與函數(shù)模板的調(diào)用規(guī)則

調(diào)用規(guī)則如下:

1.如果函數(shù)模板和普通函數(shù)都可以實現(xiàn),優(yōu)先調(diào)普通函數(shù)

2.可通過空模板參數(shù)列表強制調(diào)用函數(shù)模板

3.函數(shù)模板也可以發(fā)生重載

4.如果函數(shù)模板可以產(chǎn)生更好的匹配,優(yōu)先調(diào)用函數(shù)模板

#include<iostream>;
using namespace std;

//普通函數(shù)與函數(shù)模板調(diào)用規(guī)則
//1、如果函數(shù)模板和普通函數(shù)都可以調(diào)用,優(yōu)先調(diào)用普通函數(shù)
//2、可以通過空模板參數(shù)列表 強制調(diào)用 函數(shù)模板
//3、函數(shù)模板可以發(fā)生函數(shù)重載
//4、如果函數(shù)模板可以產(chǎn)生更好的匹配,優(yōu)先調(diào)用函數(shù)模板
void myPrint(int a, int b)
{
	cout << "調(diào)用的普通函數(shù)" << endl;
}
template<typename T>
void myPrint(T a, T b)
{
	cout << "調(diào)用的函數(shù)模板" << endl;
}

template<typename T>
void myPrint(T a, T b,T c)
{
	cout << "調(diào)用重載的函數(shù)模板" << endl;
}
void test01()
{
	int a = 10;
	int b = 20;
	//myPrint(a, b);

	//通過空模板參數(shù)列表,強制調(diào)用函數(shù)模板
	myPrint<>(a, b);

	myPrint(a, b,100);//函數(shù)重載

	//如果函數(shù)模板產(chǎn)生更好的匹配,優(yōu)先調(diào)用函數(shù)模板
	char c1 = 'a';
	char c2 = 'b';
	myPrint(c1,c2);//調(diào)用函數(shù)模板
}

int main()
{
	test01();

	system("pause");//按任意鍵繼續(xù)
	return 0;
}

總結(jié): 既然提供了函數(shù)模板,最好就不要捷供普通函數(shù),否則容易出現(xiàn)二義性

1.2.6 模板的局限性

局限性:

模板的通用性并不是萬能的

#include<iostream>;
using namespace std;
#include<string>;
//模板的局限性
//模板并不是萬能的,有些特定的數(shù)據(jù)類型,需要用具體化方式做特殊實現(xiàn)
class Person
{
public:
	Person(string name, int age)
	{
		this->m_name = name;
		this->m_age = age;
	}
	//姓名
	string m_name;
	//年齡
	int m_age;
};
//對比兩個數(shù)據(jù)是否相等函數(shù)
template<typename T>
bool myCompare(T& a, T& b)
{
	if (a == b)
	{
		return true;
	}
	else
	{
		return false;
	}
}
//利用具體化Person的版本實現(xiàn)代碼,具體化優(yōu)先調(diào)用
template<>bool myCompare(Person& p1, Person& p2)
{
	if (p1.m_name == p2.m_name && p1.m_age == p2.m_age)
	{
		return true;
	}
	else
	{
		return false;
	}


}
void test01()
{
	int a = 10;
	int b = 20;
	bool ret = myCompare(a, b);
	if (ret)
	{
		cout << "a==b" << endl;
	}
	else
	{
		cout << "a!=b" << endl;
	}
}

void test02()
{
	Person p1("Tom", 10);
	Person p2("Tom", 10);
	bool ret = myCompare(p1, p2);
	if (ret)
	{
		cout << "p1==p2" << endl;
	}
	else
	{
		cout << "p1!=p2" << endl;
	}
}

int main()
{
	test01();
	test02();

	system("pause");//按任意鍵繼續(xù)
	return 0;
}

總結(jié):

  1. 利用具體化的模板,可以解決自定義類型的通用化
  2. 學習模板并不是為了寫模板,而是在STL能夠運用系統(tǒng)提供的模板

1.3類模板

1.3.1類模板語法

類模板作用

  1. 建立一個通用類,類中的成員 數(shù)據(jù)類型可以不具體制定,用一個虛擬的類型來代表。

template<typename T>

解釋:

Template——聲明創(chuàng)建模板

Typename——表面其后面的符號是一種數(shù)據(jù)類型,可以用class代替

T——通用的數(shù)據(jù)類型,名稱可以替換,通常為大寫字母

#include<iostream>;
using namespace std;
#include<string>;
//類模板
template<class NameType,class AgeType>
class Person
{
public:
	Person(NameType name, AgeType age)//成員函數(shù)
	{
		this->m_Name = name;
		this->m_Age = age;
	}
	void showPerson()
	{
		cout << "name:"<<this->m_Name <<" age:"<<this->m_Age << endl;
	}

	NameType m_Name;
	AgeType m_Age;
};
//測試
void test01()
{
	Person<string,int> p1("孫悟空",999);
	p1.showPerson();
}

int main()
{
	test01();

	system("pause");//按任意鍵繼續(xù)
	return 0;
}

總結(jié):類模板和函數(shù)模板語法相似,在聲明模板template后面加類,此類稱為類模板。

1.3.2 類模板與函數(shù)模板區(qū)別

類模板與函數(shù)模板區(qū)別主要有兩點:

1.類模板沒有自動類型推導的使用方式

2.類模板在模板參數(shù)列表中可以有默認參數(shù)

#include<iostream>;
using namespace std;
#include<string>;
//類模板與函數(shù)模板區(qū)別主要有兩點:
template<class NameType,class AgeType = int>//僅類模板可以使用int
class Person
{
public:
	Person(NameType name, AgeType age)//成員函數(shù)
	{
		this->m_Name = name;
		this->m_Age = age;
	}
	void showPerson()
	{
		cout << "name:"<<this->m_Name <<" age:"<<this->m_Age << endl;
	}
	NameType m_Name;
	AgeType m_Age;
};
//1.類模板沒有自動類型推導的使用方式
void test01()
{
	//Person p("孫悟空", 1000);//錯誤,無法用自動類型推導
	Person<string,int> p("孫悟空",1000);//正確,只能用顯示指定類型
	p.showPerson();
}
//2.類模板在模板參數(shù)列表中可以有默認參數(shù)
void test02()
{
	Person<string> p("豬八戒", 999);
	p.showPerson();
}

int main()
{
	test01();
	test02();

	system("pause");//按任意鍵繼續(xù)
	return 0;
}

總結(jié):

  1. 類模板使用只能用顯示指定類型方式。
  2. 類模板中的模板參數(shù)列表可以有默認參數(shù)。

1.3.3 類模板中成員函數(shù)創(chuàng)建時機

類模板中成員函數(shù)和普通類中成員函數(shù)創(chuàng)建時機是有區(qū)別的:

  1. 普通類中的成員函數(shù)一開始就可以創(chuàng)建
  2. 類模板中的成員函數(shù)在調(diào)用時才創(chuàng)建
#include<iostream>;
using namespace std;
#include<string>;
//普通類中的成員函數(shù)一開始就可以創(chuàng)建
//類模板中的成員函數(shù)在調(diào)用時才創(chuàng)建
class Person1
{
public:
	void showPerson1()
	{
		cout << "Person1 show" << endl;
	}
};

class Person2
{
public:
	void showPerson2()
	{
		cout << "Person2 show" << endl;
	}
};
template<class T>
class MyClass
{
public:
	T obj;
	//類模板中的成員函數(shù)
	void func1()
	{
		obj.showPerson1();
	}
	void func2()
	{
		obj.showPerson2();
	}
};
//測試
void test01()
{
	MyClass<Person1>m;
	m.func1();
	//MyClass<Person2>m;
	//m.func2();
}

int main()
{
	test01();

	system("pause");//按任意鍵繼續(xù)
	return 0;
}

總結(jié):模板中的成員函數(shù)并不是一開始就創(chuàng)建的,在調(diào)用時才去創(chuàng)建。

1.3.4 類模板對象做函數(shù)參數(shù)

學習目標:

  1. 類模板實例化出的對象,向函數(shù)傳參的方式

一共有三種傳入方式

1.指定傳入的類型 ?——直接顯示對象的數(shù)據(jù)類型

2.數(shù)模板化 ??????——將對象中的參數(shù)變?yōu)槟0暹M行傳遞

3.整個類模板化 ??——將這個對象類型 模板化進行傳遞

#include<iostream>;
using namespace std;
#include<string>;
//類模板對象做函數(shù)參數(shù)
template<class T1,class T2>
class Person
{
public:
	Person(T1 name,T2 age)
	{
		this->m_Name = name;
		this->m_Age = age;
	}
	void showPerson()
	{
		cout << "姓名:" << this->m_Name << " 年齡:" << this->m_Age << endl;
	}
	T1 m_Name;
	T2 m_Age;
};
//1、指定傳入的類型——常用方式。
void printPerson1(Person<string,int>&p)//引用
{
	p.showPerson();
}
void test01()
{
	Person<string, int>p("孫悟空",100);
	printPerson1(p);
}
//2、參數(shù)模板化
template<class T1, class T2>
void printPerson2(Person<T1,T2>&p)//引用
{
	p.showPerson();
	cout << "T1的類型為:" << typeid(T1).name() << endl;//查看數(shù)據(jù)中的類型命令。
	cout << "T2的類型為:" << typeid(T2).name() << endl;
}
void test02()
{
	Person<string, int>p("豬八戒", 90);
	printPerson2(p);
}
//3、整個類模板化
template<class T>
void printPerson3( T &p )//引用
{
	p.showPerson();
	cout << "T的類型為:" << typeid(T).name() << endl;//查看數(shù)據(jù)中的類型命令。
}
void test03()
{
	Person<string, int>p("唐僧", 30);
	printPerson3(p);
}

int main()
{
	test01();
	test02();
	test03();

	system("pause");//按任意鍵繼續(xù)
	return 0;
}

總結(jié):

  1. 通過類模板創(chuàng)建的對象,可以有三種方式向函數(shù)中進行傳參
  2. 使用比較止泛是第一種:指定傳入的類型

1.3.5 類模板與繼承

當類模板碰到繼承時,需要注意一下幾點:

  1. 當子類繼承的父類是一個類模板時,子類在聲明的時候,要指定出父類中T的類型
  2. 如果不指定,編譯器無法給子類分配內(nèi)存
  3. 如果想靈活指定出父類中T的類型,子類也需變?yōu)轭惸0?/li>
#include<iostream>;
using namespace std;
#include<string>;
//類模板與繼承
template<class T>
class Base
{
public:
	T m;
};
//class Son:public Base//錯誤,必須要知道父類中的T類型,才能繼承給子類。
//1、當子類繼承的父類是一個類模板時,子類在聲明的時候,要指定出父類中T的類型
class Son1:public Base<int>//繼承
{
public:

};
//測試
void test01()
{
	Son1 s1;
}
//2、如果想靈活指定出父類中T的類型,子類也需變?yōu)轭惸0?template<class T1,class T2>
class Son2 :public Base<T2>//繼承
{
public:
	Son2()
	{
		cout << "T1的類型為:" << typeid(T1).name() << endl;
		cout << "T2的類型為:" << typeid(T2).name() << endl;
	}
	T1 obj;
};
void test02()
{
	Son2<int,char>s2;
}

int main()
{
	test01();
	test02();

	system("pause");//按任意鍵繼續(xù)
	return 0;
}

總結(jié):如果父類是類模板,子類需要指定出父類中T的數(shù)據(jù)類型。

#include<iostream>;
using namespace std;
#include<string>;
//類模板成員函數(shù)類外實現(xiàn)
template<class T1,class T2>
class Person
{
public:
	Person(T1 name, T2 age);
		/*{
			this->m_Name = name;
			this->m_Age = age;
		}*/
	void showPerson();
	/*{
		cout << "姓名:" << this->m_Name << " 年齡:" << this->m_Age << endl;
	}*/
	T1 m_Name;
	T2 m_Age;
};
//構(gòu)造函數(shù)的類外實現(xiàn)
template<class T1, class T2>
Person<T1,T2>::Person(T1 name, T2 age)
{
	this->m_Name = name;
	this->m_Age = age;
}
//成員函數(shù)類外實現(xiàn)
template<class T1, class T2>
void Person<T1, T2>::showPerson()
{
	cout << "姓名:" << this->m_Name << " 年齡:" << this->m_Age << endl;
}
//測試
void test01()
{
	Person<string, int>P("Tom", 20);
	P.showPerson();
}

int main()
{
	test01();

	system("pause");//按任意鍵繼續(xù)
	return 0;
}

總結(jié):類模板中成員函數(shù)類外實現(xiàn)時,需要加上模板參數(shù)列表。

1.3.7 類模板分文件編寫

學習目標:

  1. 掌握類模板成員函數(shù)分文件編寫產(chǎn)生的問題以及解決方式

問題:

  1. 類模板中成員函數(shù)創(chuàng)建時機是在調(diào)用階段,導致分文件編寫時鏈接不到

解決:

  1. 解決方式1:直接包含.cpp源文件
  2. 解決方式2:將聲明和實現(xiàn)寫到同一個文件中,并更改后綴名為.hpp,hpp是約定的名稱,并不是強制

示例:

Person.hpp中代碼:

#pragma once
#include<iostream>;
using namespace std;
#include<string>;
//類模板分文件編寫問題以及解決
template<class T1, class T2>
class Person
{
public:
	Person(T1 name, T2 age);
	void showPerson();
public:
	T1 m_Name;
	T2 m_Age;
};
//構(gòu)造函數(shù)的類外實現(xiàn)
template<class T1, class T2>
Person<T1,T2>::Person(T1 name, T2 age)
{
	this->m_Name = name;
	this->m_Age = age;
}
//成員函數(shù)類外實現(xiàn)
template<class T1, class T2>
void Person<T1, T2>::showPerson()
{
	cout << "姓名:" << this->m_Name << " 年齡:" << this->m_Age << endl;
}

類模板分文件編寫.cpp中代碼:

#include<iostream>
using namespace std;

//第一種方式,直接包含 源文件
//#include"person.cpp"

//第二種解決方式,將.h和.cpp中的內(nèi)容寫到一起,將后綴名改為.hpp文件
#include"person.hpp"

類模板分文件編寫問題以及解決
//template<class T1,class T2>
//class Person
//{
//public:
//	Person(T1 name, T2 age);
//	void showPerson();
//	T1 m_Name;
//	T2 m_Age;
//};

構(gòu)造函數(shù)的類外實現(xiàn)
//template<class T1, class T2>
//Person<T1,T2>::Person(T1 name, T2 age)
//{
//	this->m_Name = name;
//	this->m_Age = age;
//}
成員函數(shù)類外實現(xiàn)
//template<class T1, class T2>
//void Person<T1, T2>::showPerson()
//{
//	cout << "姓名:" << this->m_Name << " 年齡:" << this->m_Age << endl;
//}

//測試
void test01()
{
	Person<string, int>p("Jerry", 18);
	p.showPerson();
}

int main()
{
	test01();

	system("pause");//按任意鍵繼續(xù)
	return 0;
}

總結(jié):主流的解決方式是第二種,將類模板成員函數(shù)寫到一起,并將后綴名改為.hpp

1.3.8 類模板與友元

學習目標:

  1. 掌握類模板配合友元函數(shù)的類內(nèi)和類外實現(xiàn)

全局函數(shù)類內(nèi)實現(xiàn)——直接在類內(nèi)聲明友元即可

全局函數(shù)類外實現(xiàn)——需要提前讓編譯器知道全局函數(shù)的存在

#include<iostream>;
using namespace std;
#include<string>;
//類模板與友元
//通過全局函數(shù) 打印Person信息
//提前讓編譯器知道Person類存在
template<class T1, class T2>
class Person;
//類外實現(xiàn)
template<class T1, class T2>
void printPerson2(Person<T1, T2>& p)
{
	cout << "類外實現(xiàn)——姓名:" << p.m_Name << " 年齡" << p.m_Age << endl;
}
template<class T1, class T2>
class Person
{
	//全局函數(shù) 類內(nèi)實現(xiàn)
	friend void printPerson(Person<T1,T2>p)
	{
		cout << "姓名:" << p.m_Name << " 年齡" << p.m_Age << endl;
	}
	//全局函數(shù) 類外實現(xiàn)
	//加空模板參數(shù)列表<>
	//如果全局函數(shù) 是類外實現(xiàn),需要讓編譯器提前知道這個函數(shù)的存在
	friend void printPerson2<>(Person<T1, T2>& p);//普通函數(shù)聲明
public:
	Person(T1 name, T2 age)
	{
		this->m_Name = name;
		this->m_Age = age;
	}
private:
	T1 m_Name;
	T2 m_Age;
};
//1、全局函數(shù)在類內(nèi)實現(xiàn)
void test01()
{
	Person<string, int>p("Tom", 20);
	printPerson(p);
}
//2、全局函數(shù)在類外實現(xiàn)
void test02()
{
	Person<string, int>p("Jerry", 20);
	printPerson2(p);
}

int main()
{
	test01();
	test02();

	system("pause");//按任意鍵繼續(xù)
	return 0;
}

總結(jié):建議全局函教做類內(nèi)實現(xiàn),用法簡單,而且編譯器可以直接識別

1.3.9 類模板案例

案例描述:實現(xiàn)一個通用的數(shù)組類,要求如下:

  1. 可以對內(nèi)置數(shù)據(jù)類型以及自定義數(shù)據(jù)類型的數(shù)據(jù)進行存儲
  2. 將數(shù)組中的數(shù)據(jù)存儲到堆區(qū)
  3. 構(gòu)造函數(shù)中可以傳入數(shù)組的容量
  4. 提供對應(yīng)的拷貝構(gòu)造函數(shù)以及operator=防止淺拷貝問題
  5. 提供尾插法和尾刪法對數(shù)組中的數(shù)據(jù)進行增加和刪除
  6. 可以通過下標的方式訪問數(shù)組中的元素
  7. 可以獲取數(shù)組中當前元素個數(shù)和數(shù)組的容量

思路分析:

C++提高編程——模板,C / C++,c++

?MyArrey.hpp中的代碼:

//自己的通用的數(shù)組類
#pragma once
#include<iostream>
using namespace std;

template<class T>
class MyArrey
{
public:
	//有參構(gòu)造 參數(shù) 容量
	MyArrey(int capacity)
	{
		cout << "MyArrey有參構(gòu)造調(diào)用" << endl;
		this->m_Capacity = capacity;
		this->m_Size = 0;
		this->pAddress = new T[this->m_Capacity];
	}
	//拷貝構(gòu)造
	MyArrey(const MyArrey& arr)
	{
		cout << "MyArrey拷貝構(gòu)造調(diào)用" << endl;
		this->m_Capacity = arr.m_Capacity;
		this->m_Size = arr.m_Size;
		//this->pAddress = arr.pAddress;//錯誤!!!淺拷貝
		//深拷貝
		this->pAddress = new T[arr.m_Capacity];
		//將arr中的數(shù)據(jù)都拷貝過來
		for (int i = 0; i < this->m_Size; i++)
		{
			this->pAddress[i] = arr.pAddress[i];
		}
	}
	//operator= 防止淺拷貝問題 a = b = c
	MyArrey& operator=(const MyArrey& arr)
	{
		cout << "MyArrey 的 operator= 調(diào)用" << endl;
		//判斷原來堆區(qū)是否有數(shù)據(jù),如果有先釋放
		if (this->pAddress != NULL)
		{
			delete[] this->pAddress;
			this->pAddress = NULL;
			this->m_Capacity = 0;
			this->m_Size = 0;
		}
		//深拷貝
		this->m_Capacity = arr.m_Capacity;
		this->m_Size = arr.m_Size;
		this->pAddress = new T[arr.m_Capacity];
		//將arr中的數(shù)據(jù)都拷貝過來
		for (int i = 0; i < this->m_Size; i++)
		{
			this->pAddress[i] = arr.pAddress[i];
		}
		return *this;
	}
	//析構(gòu)函數(shù)
	~MyArrey()
	{
		if (this->pAddress!=NULL)
		{
			cout << "MyArrey析構(gòu)函數(shù)調(diào)用" << endl;
			delete[] this->pAddress;
			this->pAddress = NULL;
		}
	}

private:
	T* pAddress;//指針指向堆區(qū)開辟的真實數(shù)組
	int m_Capacity;//數(shù)組的容量
	int m_Size;//數(shù)組大小
};

類模板案例-數(shù)組類封裝.cpp中的代碼:

#include<iostream>;
using namespace std;
#include<string>;
#include"MyArray.hpp"

void test01()
{
	MyArrey<int>arr1(5);
	MyArrey<int>arr2(arr1);
	MyArrey<int>arr3(100);
	arr3 = arr1;
}

int main()
{
	test01();

	system("pause");//按任意鍵繼續(xù)
	return 0;
}

尾插法/尾刪法——案例完整代碼:

MyArrey.hpp中的代碼:

//自己的通用的數(shù)組類
#pragma once
#include<iostream>
using namespace std;

template<class T>
class MyArray
{
public:
	//有參構(gòu)造 參數(shù) 容量
	MyArray(int capacity)
	{
		cout << "MyArray有參構(gòu)造調(diào)用" << endl;
		this->m_Capacity = capacity;
		this->m_Size = 0;
		this->pAddress = new T[this->m_Capacity];
	}
	//拷貝構(gòu)造
	MyArray(const MyArray& arr)
	{
		cout << "MyArray拷貝構(gòu)造調(diào)用" << endl;
		this->m_Capacity = arr.m_Capacity;
		this->m_Size = arr.m_Size;
		//this->pAddress = arr.pAddress;//錯誤!!!淺拷貝
		//深拷貝
		this->pAddress = new T[arr.m_Capacity];
		//將arr中的數(shù)據(jù)都拷貝過來
		for (int i = 0; i < this->m_Size; i++)
		{
			this->pAddress[i] = arr.pAddress[i];
		}
	}
	//operator= 防止淺拷貝問題 a = b = c
	MyArray& operator=(const MyArray& arr)
	{
		cout << "MyArray 的 operator= 調(diào)用" << endl;
		//判斷原來堆區(qū)是否有數(shù)據(jù),如果有先釋放
		if (this->pAddress != NULL)
		{
			delete[] this->pAddress;
			this->pAddress = NULL;
			this->m_Capacity = 0;
			this->m_Size = 0;
		}
		//深拷貝
		this->m_Capacity = arr.m_Capacity;
		this->m_Size = arr.m_Size;
		this->pAddress = new T[arr.m_Capacity];
		//將arr中的數(shù)據(jù)都拷貝過來
		for (int i = 0; i < this->m_Size; i++)
		{
			this->pAddress[i] = arr.pAddress[i];
		}
		return *this;
	}
	//尾插法20230817
	void Push_Back(const T & val)
	{
		//判斷容量是否等于大小
		if (this->m_Capacity == this->m_Size)
		{
			return;
		}
		this->pAddress[this->m_Size] = val;//在數(shù)組末尾插入數(shù)據(jù)
		this->m_Size++;//更新數(shù)組大小
	}
	//尾刪法
	void Pop_Back()
	{
		//讓用戶訪問不到最后一個元素,即為尾刪,邏輯刪除。
		if (this->m_Size == 0)
		{
			return;
		}
		this->m_Size--;
	}
	//通過下標方式訪問數(shù)組中的元素  arr[0]=100。//重載operator
	T& operator[](int index)//下標
	{
		return this->pAddress[index];
	}
	//返回數(shù)組的容量
	int getCapacity()
	{
		return this->m_Capacity;
	}
	//返回數(shù)組的大小
	int getSize()
	{
		return this->m_Size;
	}
	//析構(gòu)函數(shù)
	~MyArray()
	{
		if (this->pAddress!=NULL)
		{
			cout << "MyArray析構(gòu)函數(shù)調(diào)用" << endl;
			delete[] this->pAddress;
			this->pAddress = NULL;
		}
	}
private:
	T* pAddress;//指針指向堆區(qū)開辟的真實數(shù)組
	int m_Capacity;//數(shù)組的容量
	int m_Size;//數(shù)組大小
};

類模板案例-數(shù)組類封裝.cpp中的代碼:

#include<iostream>;
using namespace std;
#include<string>;
#include"MyArray.hpp"

void printIntArray(MyArray<int>&arr)
{
	for (int i = 0; i < arr.getSize(); i++)
	{
		cout << arr[i] << endl;
	}
}
void test01()
{
	MyArray<int>arr1(5);
	for (int i = 0; i < 5; i++)
	{
		//利用尾插法向數(shù)組中插入數(shù)據(jù)
		arr1.Push_Back(i);
	}
	cout << "arr1的打印輸出為:" << endl;
	printIntArray(arr1);
	cout << "arr1的容量為:" << arr1.getCapacity() << endl;
	cout << "arr1的大小為:" << arr1.getSize() << endl;

	MyArray<int>arr2(arr1);
	cout << "arr2的打印輸出為:" << endl;
	printIntArray(arr2);
	//尾刪
	arr2.Pop_Back();
	cout << "arr2尾刪后:" << endl;
	cout << "arr2的容量為:" << arr2.getCapacity() << endl;
	cout << "arr2的大小為:" << arr2.getSize() << endl;
	
	/*MyArray<int>arr3(100);
	arr3 = arr1;*/
}
//測試自定義的數(shù)據(jù)類型
class Person
{
public:
	Person() {};
	Person(string name, int age)
	{
		this->m_Name = name;
		this->m_Age = age;
	}
	string m_Name;
	int m_Age;
};
void printPersonArray(MyArray<Person> &arr)
{
	for (int i = 0; i < arr.getSize(); i++)
	{
		cout << "姓名:" << arr[i].m_Name << "年齡" << arr[i].m_Age << endl;
	}
}
void test02()
{
	MyArray<Person> arr(10);
	Person p1("孫悟空",999);
	Person p2("韓信", 30);
	Person p3("妲己", 20);
	Person p4("趙云", 25);
	Person p5("安其拉", 27);
	//將數(shù)據(jù)插入到數(shù)組中
	arr.Push_Back(p1);
	arr.Push_Back(p2);
	arr.Push_Back(p3);
	arr.Push_Back(p4);
	arr.Push_Back(p5);
	//打印數(shù)組
	printPersonArray(arr);
	//輸出容量
	cout << "arr的容量為:" << arr.getCapacity() << endl;
	//輸出大小
	cout << "arr的大小為:" << arr.getSize() << endl;
}

int main()
{
	test01();
	test02();

	system("pause");//按任意鍵繼續(xù)
	return 0;
}

總結(jié):

能夠利用所學知識點實現(xiàn)通用的數(shù)組

模板結(jié)束。文章來源地址http://www.zghlxwxcb.cn/news/detail-662501.html

到了這里,關(guān)于C++提高編程——模板的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • C++提高編程

    C++提高編程

    ????????●本階段主要針對C++泛型編程和STL技術(shù)做詳細講解,探討C++更深層的使用 1模板 1.1模板的概念 模板就是建立通用的模具,大大提高復用性 例如生活中的模板 一寸照片模板: ?1.2函數(shù)模板 ????????●C++另一種編程思想稱為泛型編程,主要利用的技術(shù)就是模板 ?

    2024年02月03日
    瀏覽(16)
  • 第一百一十四天學習記錄:C++提高:類模板案例(黑馬教學視頻)

    第一百一十四天學習記錄:C++提高:類模板案例(黑馬教學視頻)

    main.cpp代碼: myarray.hpp代碼: 輸出: 總結(jié):能夠利用所學知識點實現(xiàn)通用的數(shù)組。 個人感悟:學習了這個案例之后接下來的課程就是STL了,STL其實在我工作中寫代碼時經(jīng)常碰到,尤其是在讀同事代碼的時候,因為沒有學過,通過自行百度獲得碎片的知識導致讀起來很很吃力

    2024年02月16日
    瀏覽(23)
  • 【C++】——模板(泛型編程+函數(shù)模板+類模板)

    【C++】——模板(泛型編程+函數(shù)模板+類模板)

    之前我們學習了函數(shù)重載,讓我們在寫相似函數(shù)的時候非常方便,但函數(shù)重載還有很多不足的地方,比如,每次寫相似函數(shù)的時候,都要我們重新重載一個邏輯、代碼幾乎一樣的函數(shù),這就導致了我們的效率變低,所以我們今天來學習C++模板的相關(guān)知識點,學習完模板之后,

    2024年02月05日
    瀏覽(26)
  • C++提高編程——STL:string容器、vector容器

    C++提高編程——STL:string容器、vector容器

    本專欄記錄C++學習過程包括C++基礎(chǔ)以及數(shù)據(jù)結(jié)構(gòu)和算法,其中第一部分計劃時間一個月,主要跟著黑馬視頻教程,學習路線如下, 不定時更新,歡迎關(guān)注 。 當前章節(jié)處于: ---------第1階段-C++基礎(chǔ)入門 ---------第2階段實戰(zhàn)-通訊錄管理系統(tǒng), ---------第3階段-C++核心編程, -----

    2024年01月23日
    瀏覽(22)
  • C++核心編程——內(nèi)存分區(qū)、引用、函數(shù)提高和函數(shù)重載

    本專欄記錄C++學習過程包括C++基礎(chǔ)以及數(shù)據(jù)結(jié)構(gòu)和算法,其中第一部分計劃時間一個月,主要跟著黑馬視頻教程,學習路線如下, 不定時更新,歡迎關(guān)注 。 當前章節(jié)處于: ---------第1階段-C++基礎(chǔ)入門 ---------第2階段實戰(zhàn)-通訊錄管理系統(tǒng), ==== 第3階段-C++核心編程 , --------

    2024年01月22日
    瀏覽(23)
  • 【C++初階】八、初識模板(泛型編程、函數(shù)模板、類模板)

    【C++初階】八、初識模板(泛型編程、函數(shù)模板、類模板)

    ========================================================================= 相關(guān)代碼gitee自取 : C語言學習日記: 加油努力 (gitee.com) ?========================================================================= 接上期 : 【C++初階】七、內(nèi)存管理 (C/C++內(nèi)存分布、C++內(nèi)存管理方式、operator new / delete 函數(shù)、定位new表

    2024年02月04日
    瀏覽(19)
  • c++模板編程2-函數(shù)模板的定義和使用

    兩階段編譯檢查 在實例化模板的時候,如果模板的參數(shù)類型不支持模板中用到的操作符,將會遇到編譯期錯誤,例: 以上例子 add(a, b) 會在編譯器報錯,但在模板定義的地方并沒有出現(xiàn)錯誤提示,這是因為模板是分兩步編譯的: 在模板定義階段,模板的檢查并不包含類型參

    2024年02月06日
    瀏覽(17)
  • C++之模板編程

    模板及泛型編程與面向?qū)ο笥懈镜膮^(qū)別:顯式接口和運行期多態(tài)仍存在,但重要性降低,隱式接口和編譯期多態(tài)移到前頭了;C++中的元編程指針對類型以及常數(shù)進行推導,演算和構(gòu)造等操作,這些操作的共同特點是都是面向編譯期邏輯,大多通過模板技巧實現(xiàn) 經(jīng)驗總結(jié) 只

    2024年02月03日
    瀏覽(14)
  • 【C++】C++泛型編程 | 模板初階

    【C++】C++泛型編程 | 模板初階

    ??????? 個人主頁:簡 料 ???? 所屬專欄:C++ ???? 個人社區(qū):越努力越幸運社區(qū) ???? 簡? ? ?? 介: 簡料簡料,簡單有料~在校大學生一枚,專注C/C++/GO的干貨分享,立志成為您的好幫手 ~ C/C++學習路線 (點擊解鎖) ?? C語言 ?? 初階數(shù)據(jù)結(jié)構(gòu)與算法 ?? C++ ??

    2024年02月08日
    瀏覽(29)
  • C++泛型編程之模板

    C++泛型編程之模板

    目錄 一、什么是泛型編程? 二、函數(shù)模板 2.1函數(shù)模板的概念 2.2函數(shù)模板格式 2.3函數(shù)模板的原理 ?2.5函數(shù)模板的實例化 2.6模板參數(shù)的匹配原則 三、類模板 3.1類模板的定義格式 3.2 類模板的實例化 四、非類型模板參數(shù) 五、模板的特化 5.1模板特化的概念: 5.2函數(shù)模板特化 5

    2024年02月07日
    瀏覽(19)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包