自学笔记——C++泛编程(基础)

一、自动推导

1、概念

使用auto关键词声明变量类型,编译器自动推导出数据的类型(类似python中声明变量)
对比:

void test1() {
	int a = 1;
	double b = 1.3;
	string c = "hello";
	cout << a << " " << b << " " << c << endl;
	cout << sizeof(a) << " " << sizeof(b) << " " << sizeof(c) << endl;
	cout<<endl;
	//对比:
	auto a1 = 2;
	auto b1 = 2.1;
	auto c1 = "world";
	cout << a1 << " " << b1 << " " << c1 << endl;
	cout << sizeof(a1) << " " << sizeof(b1) << " " << sizeof(c1) << endl;
}

在这里插入图片描述

2、使用场景

1)函数指针

int myfun(int a,int b) {
	return a + b;
}
void test2() {
	//声明函数指针
	int(*p)(int, int);
	p = myfun;
	cout << p(1, 2) << endl;
	//auto自动推导
	auto p1 = myfun;
	cout << p1(3, 4) << endl;
}

结果:
在这里插入图片描述

3、注意事项

  1. 使用auto声明时必须赋初值
  2. 等号右边可以是数值、表达式、函数返回值
  3. 不可作函数形参
  4. 不能直接声明数组
  5. 不能定义类的非静态成员变量

二、函数模板

1、概念

函数模板是通用的函数描述,使用任意类型(泛型)描述函数,编译器根据传入的实参类型和模板生成函数定义(代码),此过程称为函数的实例化。与函数重载功能类似但更为简洁。
函数模板仅作为函数的描述,不具有实体,在实例化的时候才生成对应的函数空间。

2、例子

1)单个通用参数

//函数模板
template<typename anytype>
void myswap(anytype &a, anytype &b) {
	anytype t = a;
	a = b;
	b = t;
}
void test3() {
	int a = 1, b = 2;
	myswap(a,b);
	cout << a << " " << b << endl;
}

结果:
在这里插入图片描述

2)多个通用参数

//多个通用参数的函数模板
template<typename anytype1,typename anytype2>
void myfun1(anytype1 a, anytype2 b) {
	cout << a << endl;
	cout << b << endl;
}
void test5() {
	int a = 1, b = 'A';
	myfun1(a, b);
}

结果:
在这里插入图片描述

3)非通用的参数

template<typename T,int n>
T factorial(T t1) {
	T t=t1;
	for (int i = 0; i < n-1; i++) {
		t = t * t1;
	}
	return t;
}

示例中 int n 是非通用的模板参数,使用模板函数时需要显示地指定参数类型,对于非通用的参数n,指定n的值即可,测试如下:

void test11() {
	cout << factorial<int,3>(5) << endl;;
}

结果:
在这里插入图片描述

3、注意事项

  1. 类中可以使用函数模板,虚函数和析构函数不能用
  2. 传入的实参必须是相同的数据类型,如果不传入实参需手动指定数据类型
  3. 函数模板无法隐式转换数据类型,如需转换需手动指定数据类型,示例如下:
template<typename anytype>
anytype myadd(anytype a, anytype b) {
	anytype c = a + b;
	return c;
}
void test4() {
	int a = 1;
	char b = '2';
	cout << myadd<int>(a, b) << endl;
	cout<<myadd<char>(a,b) << endl;
	cout << a + (int)b << endl;
	cout << a + b << endl;
}

结果:
在这里插入图片描述

  1. 函数模板无法隐式转换数据类型,如需转换需手动指定数据类型

三、函数模板的具体化

函数模板的特例,调用时编译器优先匹配具体化的模板再匹配通用的函数模板
优先级对比:
1、具体化函数模板优先级高于通用函数模板

template <typename anytype>
void myprint(anytype a) {
	cout << "通用型:" <<a<< endl;
}
//函数模板具体化
template<> 
void myprint(int a) {
	cout << "具体化:" <<a<< endl;
}
void test6() {
	int a = 1;
	char b = 'a';
	myprint(a);
	myprint(b);
}

结果:
在这里插入图片描述
2、普通函数优先级高于所有函数模板,但是若函数模板有更好的参数匹配,则函数模板高于普通函数:

template <typename anytype>
void myprint(anytype a) {
	cout << "通用型:" <<a<< endl;
}
//函数模板具体化
template<> 
void myprint(int a) {
	cout << "具体化:" <<a<< endl;
}
//添加普通函数
void myprint(int a) {
	cout << "普通:" << a << endl;
}
void test6() {
	int a = 1;
	char b = 'a';
	myprint(a);
	myprint(b);
}

结果:
传入字符型参数b,结果调用的是函数模板
在这里插入图片描述
3、函数调用时加空参数跳过普通函数强制执行函数模板:

void test6() {
	int a = 1;
	char b = 'a';
	myprint<>(a);//加空参数
	myprint(b);
}

结果:
在这里插入图片描述

四、函数模板分文件编写

函数的声明和定义可以在不同文件中实现,

  • 普通函数和特例化的函数模板在头文件中声明,在源文件中定义。
  • 通用型函数模板声明和特例化只能在同译文件中
    头文件:
#include <iostream>
using namespace std;

//声明普通函数
void myprint_(int a);

//声明函数模板
template<typename anytype>
void myprint_(anytype a) {
	cout << "通用型:" << a << endl;
}
//声明具体化函数模板
template<>
void myprint_(int a);

源文件:

#include <myhead.h>
//普通函数声明
void myprint_(int a) {
	cout << "普通:" << a << endl;
}

//特例化声明
template <>
void myprint_(int a) {
	cout << "特例化" << a << endl;
}

主函数:

void test7() {
	myprint_(1);
	myprint_<>(2);
	myprint_('A');
}

结果:
在这里插入图片描述

五、自动推导的函数类型

1、类型说明符decltype

能够返回一个数据、表达式或函数的数据类型或引用,且在返回过程中不会发生表达式或函数的执行

int myfun2() {
	cout << "hello world" << endl;
	return 0;
}
void test8() {
	int a = 1;
	decltype(a) x1=1; cout << "x1=" << x1 << endl;
	decltype(myfun2()) x2 = 2; cout << "x2=" << x2 << endl;
	decltype(++a) x3 = ++a; cout << "x3=" << x3 << endl;
	decltype(myfun2)* x4; x4 = myfun2; x4();
	decltype((myfun2)) x5 = myfun2; x5();
}

结果:
在这里插入图片描述

2、自动推导的函数类型实现

template<typename anytype1,typename anytype2>
auto myadd2(anytype1 a, anytype2 b) -> decltype(a+b) {
	auto t = a + b;
	return t;
}
void test9() {
	cout << myadd2(1, 2.3) << endl;
	cout << myadd2(1, 'A') << endl;
}

注:C++14对函数类型推导规则进行了优化,简化写法:

template<typename anytype1,typename anytype2>
auto myadd2(anytype1 a, anytype2 b){...}

结果:
在这里插入图片描述

六、模板类

1、模板类的定义

模板类通用地描述类的数据类型,定义出来的 anytype 可以在类中的任意位置使用

template <class anytype>
class Mycla {
	anytype a;
public:
	Mycla(anytype a1) { 
		a = a1; 
	}
	anytype get_a() {
		return a;
	}
};

2、使用模板类创建对象

需要显式地指定数据类型,代码含义:实例化 int型Mycla 类,并创建对象 obj1

void test10() {
	Mycla<int> obj1(1);
	cout << obj1.get_a() << endl;
}

结果:
在这里插入图片描述

3、注意事项

  1. 在指定多个通用参数时可以设置缺省的数据类型
template<class anytype1,class anytype2=char>
class Mycla2 {
	anytype1 a;
	anytype2 b;
public:
	Mycla2(anytype1 a1, anytype2 b1) {
		a = a1;
		b = b1;
	}
};
void test10() {
	Mycla2<int> obj2(1,'A');
}
  1. 在类外实现成员函数
template<class T1,class T2=char>
class Mycla2 {
	T1 a;
	T2 b;
public:
	Mycla2(T1 a1, T2 b1) {
		a = a1;
		b = b1;
	}
	T1 print_a();
	T2 print_b();
};
//类外实现成员函数
template<class T1,class T2>
T1 Mycla2<T1, T2>::print_a() {
	cout << a << endl;
	return a;
}
template<class T1, class T2>
T2 Mycla2<T1, T2>::print_b() {
	cout << b << endl;
	return b;
}
void test10() {
	Mycla2<int> obj2(1,'A');
	obj2.print_a();
	obj2.print_b();
}

结果:
在这里插入图片描述

  1. 使用 new 语句创建模板对象
template <class anytype>
class Mycla {
	anytype a;
public:
	Mycla(anytype a1) {
		a = a1;
	}
	anytype get_a() {
		return a;
	}
};
void test10() {
	Mycla<int>* obj = new Mycla<int>(3);
	cout << obj->get_a() << endl;
	delete(obj);
}

结果:
在这里插入图片描述

七、模板类的具体化

模板类的具体化和函数的具体化类似,可以在定义时将部分参数具体化,假设一个未具体化的模板类定义如下:

template <class T1,class T2>
class A {
	T1 a;
	T2 b;
};

1、部分具体化

template<class T1>
class A<T1, int> {
	T1 a;
	int b;
};

2、完全具体化

template<>
class A<int, char> {
	int a;
	char b;
};

需要注意具体化的前提是要先定义未具体化的类模板,否则不存在具体化一说,和函数模板的具体化是一样的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值