C++ 重载与模板

函数重载:

即C++编译器通过检测同名函数不同的参数列表来进行匹配的行为

几个要点:

  • 函数重载的关键是函数的参数列表,也称函数特征标,包括参数的数目,类型,顺序
  • 某类型与其引用将视为同一特征标
  • const与非const视为不同特征标,const参量可以接受非const变量(反之不可以),假如存在两个参数分别是const和非const的同名函数,传入非const变量时优先匹配非const参数的函数
函数模板:

例交换模板:

template < typename Anytype>
void Swap(Anytype &a,Anytype &b)
{
	Anytype temp;
	temp=a;
	a=b;
	b=temp;
}
  • 其中关键字template和typename是必须的,但typename可以替换成class
  • 当交换两个int变量的值时,编译器会自动按模板创建函数,并将Anytype替换成int.
  • 同样的,模板也可以进行重载
  • 我们也可以不通过参数实例化函数模板,即在函数调用时在函数名后加< 参数类型1,参数类型2…> (参数)便可指定函数模板生成什么参数类型的函数。
函数模板和函数的次序:

在有多个函数和函数模板名字相同的情况下,编译器如下处理一条函数调用语句

  1. 先找参数完全匹配的普通函数(非由模板实例化而得的函数)。
  2. 再找参数完全匹配的模板函数。
  3. 再找实参数经过自动类型转换后能够匹配的普通函数。
  4. 上面的都找不到,则报错。
关键字decltype(C++11)
int x;
decltype(x) y;//等价于 int y;
decltype((x)) y;//等价于int & y;

一般用于当模板中某个表达式类型未知时。

后置返回类型(C++11)

对于如下代码:

template<class T1,classT2>
? type gt(class T1,class T2)
{	...
	return x+y;
}

首先我们无法知道T1+T2的类型,这看起来似乎可以使用decltype(x+y)来解决,但实际上此时还没有声明x,y。
所以我们采用后置返回类型来解决:

double h(int x);//等价于auto h(int x) -> double;
所以上例可定义为:
template<class T1,class T2>
auto gt(class T1,class T2) -> decltype(x+y)
{
	...
	return x+y;
}

运算符重载:

  • 运算符重载的实质是函数重载
  • 可以重载为普通函数,也可以重载为成员函数
  • 把含运算符的表达式转换成对运算符函数的调用。
  • 把运算符的操作数转换成运算符函数的参数。
  • 运算符被多次重载时,根据实参的类型决定调用哪个运算符函数。
  • 重载为成员函数时对象本身就是第一个参数。

运算符重载的形式

返回值类型 operator 运算符(形参表)
{
……
}
赋值运算符 ‘=’ 的重载
  • 赋值运算符“ =”只能重载为成员函数
  • 重载时返回值尽量为引用以保持原有特性。
友元与重载

什么时候使用友元重载?

  1. 对某个二目运算符重载成员函数进行补充
class A
{	...
	A operator + (int i);
	friend A operator + (int i,A a);
};
//此时a+i与i+a均合法,维持了+号原本的特性。
  1. 流插入和流提取运算符重载时一般需要写成友元函数
自增,自减运算符的重载

自增运算符++、自减运算符–有前置/后置之分,为了区分所重载的是前
置运算符还是后置运算符, C++规定:

  • 前置运算符作为普通一元运算符重载
  • 后置运算符作为二元运算符重载,多写一个没用的参数

一般重载前置运算符时需要返回其引用,而重载后置运算符时则返回其对象。这也是为了贴合原来++、- - 运算符的性质

强制类型转换运算符的重载
operator int() {};
  • 类型强制转换运算符被重载时不能写返回值类型,实际上其返回值类型就 是该类型强制转换运算符代表的类型
  • 一般作为成员函数重载

运算符重载的注意事项

  1. C++不允许定义新的运算符 ;
  2. 运算符重载不改变运算符的优先级;
  3. 以下运算符不能被重载:“ ..*” 、“ ::” 、“ ?:” 、 sizeof
  4. 重载运算符()、 []、 ->或者赋值运算符=时,运算符重载函数必须声明为
    类的成员函数。

类模板

定义
template <class 类型参数1,class 类型参数2,……> //类型参数表
class 类模板名
{
成员函数和成员变量
};

类模板里成员函数的写法:

template <class 类型参数1, class 类型参数2, ……> //类型参数表
返回值类型 类模板名<类型参数名列表>::成员函数名(参数表)
{
函数体
}

用类模板定义对象的写法:
类模板名 <真实类型参数表> 对象名(构造函数实参表);

类模板的“<类型参数表>”中可以出现非类型参数:

template <class T, int size>
class CArray{
T array[size];
public:
void Print( )
{
for( int i = 0;i < size; ++i)
cout << array[i] << endl;
}
};
CArray<double,40> a2;
CArray<int,50> a3; //a2和a3属于不同的类
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值