重载
C++ 允许在同一作用域中的某个函数和运算符指定多个定义,分别称为函数重载和运算符重载 。
重载声明是指一个与之前已经在该作用域内声明过的函数或方法具有相同名称的声明,但是它们的参数列表和定义(实现)不相同。 其次,不会根据返回值不同进行重载
函数重载
//返回值相同或类似,名字相同;参数列表不同,定义不同
void print(int i)
{
cout << "整数为: " << i << endl;
}
void print(double f)
{
cout << "浮点数为: " << f << endl;
}
void print(char c[])
{
cout << "字符串为: " << c << endl;
}
int print(int i)//编译器报错,无法根据返回值进行重载
{
cout << "整数为: " << i << endl;
}
运算符重载
c++中有许多自定义的运算符,我们也可以对它们进行重载。重载的运算符是具有特殊名字的函数,函数名是由关键字 operator 和其后要重载的运算符符号构成的。与其他函数一样,重载运算符有一个返回类型和一个参数列表。
一元运算符有一个参数,二元运算符有两个参数。
对于二元运算符来说,左侧对象传递给第一个参数,右侧对象传递给第二个参数。例如:
int operator+(int,int);
如果一个运算符函数是成员函数,则它的第一个运算对象绑定到隐式的this指针上,因此,成员运算符函数显示参数数量比运算符的运算对象少一个。例如:
class Point
{
public:
Point(){x=1;}
~Point(){}
Point operator+(const Point &p) const//定义了+号运算符
{
Point tmp;
tmp.x = p.x + x;
tmp.y = p.y + y;
return tmp;
}
//输入输出运算符因为左边参数必须是ostream类型,一般用友元
friend ostream &operator<<(ostream &os,const Point &p);
public:
int x;
int y;
};
ostream &operator<<(ostream &os,const Point &p)
{
os<<p.x<<p.y<<endl;
return os;
}
注意事项
(1)有四个运算符不能够被重载:
-
“.”,成员选择符
-
“.*”,成员对象选择符
-
“::”,域解析操作符
-
“?:”,条件操作符
前两个运算符不能重载是为了保证访问成员的功能不能被改变,域运算符合sizeof运算符的运算对象是雷西兴而不是变量或一般表达式,不具备重载的特征。
(2)重载不能改变运算符运算对象的个数
如关系运算符"<“或”>“等是双目运算符,重载后仍为双目运算符,需要两个参数。运算符”+","-"等既可以作为单目运算符,也可以作为双目运算符,可以分别将它们重载为单目运算符或双目运算符。
(3)重载不能改变运算符的优先级别
例如"*“和”/“优先级高于”+"、"-",不论怎样进行重载,各运算符之间的优先级不会改变。
(4)重载不能改变运算符的结合性。
如,赋值运算符“=”是右结合性,重载后仍为右结合性。
(5)重载运算符的函数不能有默认参数
否则就改变了运算符参数的个数
(6)用于类对象的运算符一般必须重载,但有两个例外,"=“和”&"不必用户重载
系统为每一个新声明的类重载了一个赋值运算符,它的作用是逐个复制类中的数据成员,成员地址运算符&也不必重载,它能返回类对象在内存中的其实地址。
(7)应当使重载运算符的功能类似于该运算符作用域标准类型数据时候时锁实现的功能。
例如,我们回去重载"+"以实现对象的相加,而不会使其相减,否则不符合我们的认知。
++运算符的重载
区分递增和递减运算符的前置版本和后置版本:
前置版本,当前语句执行前完成递增或递减操作,没有传入形参
后置版本,当前语句执行结束后完成递增或递减操作,接收一个额外的不被使用的(int)类型的形参
//前++
Point& Point::operator++()
{
x++;
y++;
return *this;
}
//后++
Point& Point::operator++(int)//亚元,无实际意义
{
x++;
y++;
return *this;
}
括号重载(仿函数)
我们可以对小括号进行重载,就可以像使用函数一样使用该类的对象。
//左边的括号是需要重载的括号运算符,右边的括号是传入参数列表
void Point::operator()(void)
{
cout << x << endl;
cout << y << endl;
}
int main()
{
Point p1;
p1();//类似于函数调用
}
new和delete的重载
new和delete的重载,利用c语言中的malloc和free来进行重载。
//重载以后也依然能够触发构造和析构函数
void* Point::operator new[](size_t size)
{
cout<<"重载了new[]操作符"<<endl;
return malloc(size);
}
void Point::operator delete(void *p)
{
cout<<"重载了delete操作符"<<endl;
if(p != NULL)
{
free(p);
p = NULL;
}
}
不建议重载&&和||
因为二者具有短路现象,而重载以后不具有该特性。
int a = 0;
int b = 10;
if(a && (a+b))//当左边表达式为0时,则右边表达式不执行,相当于短路
{
...
}