重生之C++学习:模板初阶

  • 泛型编程
  • 函数模板
  • 类模板

    目录

    泛型编程

    函数模板

    类模板


泛型编程

   在之前的学习中,我们学习过函数重载,可以借助一样的函数名,重载不同的参数类型,以swap函数重载int,double,char3种类型为例,我们发现还是会有一点的麻烦(也会存在代码复用率低和可维护性低,容易出错等问题),在这个基础上,衍生出了模板,泛型编程

模板的定义

template
template

template        // stl中喜欢用class,class与template几乎一致

函数模板

重生之C++学习:模板初阶_第1张图片

对于函数重载,我们需要多写几个函数(重复的事情)借助洗衣机来洗衣服

// 函数重载
void swap(int* a, int* b){

    int tmp = *a;
    *a = *b;
    *b = tmp;
}
void swap(double* a, double* b){

    double tmp = *a;
    *a = *b;
    *b = tmp;
}
void swap(char* a, char* b){

    char tmp = *a;
    *a = *b;
    *b = tmp;
}

那么如果是用泛型,编译器用模板实例化生成对应的swap函数  就是   上面重复的函数重载的内容

template

void swap(T* a, T* b){

    T tmp = *a;
    *a = *b;
    *b = tmp

}
// 通过泛型编程 我们不需要对swap进行多次重载,直接一次到位

虽然最终公用的是一样的main函数,但是泛型编程显然更加方便简洁,也更加高级

int main() {
	int i = 10;
	int j = 20;
	swap(i, j);
	cout << i <<" " << j << endl;

	double x = 1.1;
	double y = 2.2;
	swap(x, y);
	cout << x << " " << y << endl;
}

利用模板反汇编发现形成int类型的swap和double的swap,俩个swap不一样

重生之C++学习:模板初阶_第2张图片

这里就是,在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应的函数以供调用。比如:当double抑或是int类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然后专门生成处理double类型的代码!!!

类模板

重生之C++学习:模板初阶_第3张图片

template 

class Stack {

public:
	Stack(size_t capacity = 4) {

		_array = new T[capacity];
		_capacity = capacity;
		_stackTop = 0;
		cout << "构造 启动!" << endl;
	}
	~Stack() {

		delete[] _array;
		_array = nullptr;
		_stackTop = _capacity = 0;
		cout << "析构 启动!" << endl;
	}
	Stack(const Stack& s) {

		T* _array = new T[s._capacity];
		_capacity = s._capacity;
		_stackTop = s._stackTop;
	}
	void push(const T& value) {

		_array[_stackTop] = value;
		_stackTop++;
	}
	void pop() {

		_stackTop--;
	}

private:
	T* _array;
	int _capacity;
	int _stackTop;
};

int main() {


	Stack st1;		// 专门为int的栈

	Stack st2;	// 专门为double的栈
}

这样我们通过类模板就能在不同的类型来实现啦

模板初阶细节部分

Rart2:当我们在想如果有一个 类函数Add,当你传入得参数不是同一个类型时,又需要怎么解决呢?就比如老妈叫你去洗碗,老爸叫你去拖地,要你同时进行那你听谁的呢?编译器就像这个“你”一样苦恼,所以就需要强制执行一个(强制类型转换),抑或是叫来爷爷来决定也就是(显示实例化)

template

T Add(const T& a, const T& b){

    return a + b;
}
int main(){

    cout << Add(1, 2) << endl;
    // 会报错 因为传入参数编译器分不清是要返回int还是double
    cout << Add(1.3, 2) << endl;
    // 那么就需要强制类型转换
    cout << Add((int)1.3, 2) << endl;
    cout << Add(1.3, (double)2) << endl;

    // 显示实例化(也可以让编译器明白需要返回什么
    cout << Add(1.3, 2) << endl;
    cout << Add(1.3, 2) << endl;   
}

重生之C++学习:模板初阶_第4张图片

Part2:当同时有普通的add函数和函数模板add,编译器在同种且符合普通add的函数和函数模板,会优先选择普通add

int Add(int& a, int& b){
    
    return a + b;
}
template

T Add(const T& a, const T& b){

    return a + b;
}

int main(){
    // 编译器为了省事不会调用函数模板 而是普通add
    cout << Add(x, y) <(x,y) <

Part3:类模板的定义与声明需要放在同一个部分(文件)

你可能感兴趣的:(学习)