目录
1.重载
2.运算符
3.一般实现方式
~~~~ 3.1成员函数实现
~~~~ 3.2友元函数实现
4.特殊情况
~~~~ 4.1只能用友元函数实现
~~~~ 4.2只能用成员函数实现
~~~~ 4.3不能重载
~
所谓运算符重载,本质上也是对函数重载。
根据不同形参类型调用首部相同的不同函数。
这是静态多态的表现。
指的诸如:
+
,-
,*
,/
,[]
,()
,int
等。它们本质上是函数。
注意,此处提到的int
是强制类型转换运算符。
运算符重载一般有成员函数和友元函数两种实现方式。
基本语法是:返回值类型 operator运算符(形参列表)
特殊地,对于类型转换运算符,无需写返回值类型,因为转换的类型已经确定了返回值类型。
E g 1 : Eg1: Eg1:重载+
实现自定义整数类型Myint
的数据成员x
的加法。
#include
using namespace std;
class myint
{
int x;
public:
myint(int x) { this->x = x; }
//重载+
myint operator+(myint& y)
{
int temp = this->x + y.x;
myint m(temp);
return m;
}
void show()
{
cout << "x = " << x << endl;
}
};
int main()
{
myint a(1), b(2), c(0);
c = a + b;
c.show();//输出结果为3
return 0;
}
E g 2 : Eg2: Eg2:重载 “ + + ” “++” “++”运算符实现自定义整数类型myint
的前置递增运算符。
//重载++
myint& operator++()
{
x++;
return *this;
}
注意
1.前置递增必须返回引用。
2.为了以示后置递增与前置递增的区别,后置递增需要增加占位记号。
myint operator++(int)
{
myint temp = *this;
x++;
return temp;
}
E g 3 : Eg3: Eg3:重载myint
的=
运算符实现连等。
myint& operator=(myint& temp)
{
this->x = temp.x;
return *this;
}
注意
为实现连等,必须返回引用
可以在主函数调用如下:
int main()
{
myint a(1), b(2);
myint c(3);
c = b = a;
c.show();
return 0;
}
此时输出 x = 1 x=1 x=1
既然是成员函数,除了直接用运算符调用以外,也可以使用:
a.operator=(b);
E g 4 : Eg4: Eg4:采用外部函数方法,实现 E g 1 Eg1 Eg1中的+
的重载。
#include
class myint
{
friend myint operator+(myint& a, myint& b);
int x;
public:
myint(int x) { this->x = x; }
void show() { std::cout << "x = " << x << std::endl; }
};
myint operator+(myint& a, myint& b)
{
int temp = a.x + b.x;
myint ans(temp);
return ans;
}
int main()
{
myint a(1), b(1);
a = a + b;
a.show();
return 0;
}
注意
外部函数无法直接访问类内数据,要设置为友元函数,但会破坏封装性。
另外,外部函数实现重载后也可以采用函数调用的方法,如:
myint a(1), b(1), c(5);
c = operator+(a, b);
E g 4 : Eg4: Eg4:重载<<
运算符,打印myint
类型数据;要求:可以连打印多个数据。
分析:
<<
本质上是一个函数,当我们使用如下语句:
cout << x << endl;
本质上我们是通过对象cout
调用了operatpor<<
这个函数。
如果要实现连续打印,调用结束后必然还是要返回cout
这个对象。
注意,cout
是属于ostream
类的,且全局只有这一个对象。
因此,返回值类型必须是ostream
类的引用且形参中也必须如此。
如果采用成员函数实现,那么应该写为:
ostream& operator<<(ostream& cout)
{
cout << x;
return cout;
}
这时,根据调用的顺序应该是:
int main()
{
myint a(1);
a << cout << endl;
//cout << a;错误
return 0;
}
显然不是我们期望的结果。
当然了,我们也无法在cout
中重载<<
,因为这已经封装好了。
因此,重载<<
运算符,只能采用友元函数,如下:
#include
using namespace std;
class myint
{
friend ostream& operator<<(ostream& cout, myint& m);
int x;
public:
myint(int x) { this->x = x; }
};
ostream& operator<<(ostream& cout, myint& m)
{
cout << m.x;
return cout;
}
int main()
{
myint a(1);
cout << a << " " << endl;
return 0;
}
值得注意的是,此处的ostream& cout
不能加const
修饰。
因为输出会先进入到ostream
流,再到屏幕显示,也就是会改变其属性。
因此不能加const
。
~
C + + C++ C++规定,以下运算符只能通过成员函数来重载。
运算符 | 含义 |
---|---|
= |
赋值运算符 |
() |
函数调用运算符 |
[] |
下标运算符 |
-> |
指针访问类成员的运算符 |
int 等 |
强制类型转换运算符 |
对=
无法重载为友元函数进行解释如下:
示例如下代码,
#include
using namespace std;
class myint
{
public:
int x;
myint(int x)
{
this->x = x;
cout << "constructor1" << endl;
}
myint(){ cout << "constructor2" << endl; }
};
int main()
{
myint a;
a = 20;
return 0;
}
输出为:
这说明语句a=20
会默认去调用与右值匹配的构造函数,也就是转为了a(20)
如果我们在成员函数内重载了=
#include
using namespace std;
class myint
{
public:
int x;
myint(int x)
{
this->x = x;
cout << "constructor1" << endl;
}
myint(){ cout << "constructor2" << endl; }
myint& operator=(int x)
{
this->x = x;
cout << "operator=" << endl;
return *this;
}
};
int main()
{
myint a;
a = 20;
return 0;
}
输出为:
可以看出,此时根本没有调用与右值匹配的构造函数。
而如果我们在外部实现重载=
,这个函数是友元函数,它并不属于类。
当程序执行到a=20
,类中若有匹配的构造函数,且外部友元函数也匹配,这时候就会出现二义性。无法判断应该调用哪一个函数。
另外,对于[]
举例说明:
假设我们采用采用友元函数实现,并如下设置形参顺序:
char operator[](int idx, mys& Mys)
那么我们显然调用时要写成下面这样的语句:
char temp = 1[Mys];
这显然是不合适的,因此 C + + C++ C++规定其重载只能用成员函数实现。
~
E g 5 : Eg5: Eg5:实现自定义myint
类型到int
类型的转换。
class myint
{
int x;
public:
myint(int x)
{
this->x = x;
cout << "myint constructor" << endl;
}
//对象强制转换为一般类型
operator int()
{
return x;
}
};
int main()
{
myint m(9);
cout << (int)m << endl;
}
运算符 | 含义 |
---|---|
: |
成员运算符 |
.* |
成员指针运算符 |
:: |
作用域解析运算符 |
?:: |
三目运算符 |
sizeof |
求字节运算符 |
const_cast |
强制类型转换运算符 |