运算符(操作符--operator)重载引入分析
对于基于数据类型---int
int i;
int j;
int k = i + j; //ok,因为在C编译器,已经封装了运算符的含义(重载),在原始
的计算中,+ - ...,只能做数学运算,但是在C语言,能够进行两个变量的加或者减
,所以说C语言赋给了运算符的新的意义,但是本质上还是做它的运算符,C语言中,
这种技术,并没有开放给设计者。
在C++中,通常是以自定义的类型来开发,
A a1;
A a2;
A a3 = a1 + a2; //如果可以的话,那么C++中,可以完成两个对象之间的相加
//默认是不可以的,但是,C++把运算符和重载机制,开放给类设计
//者,可以根据自己,给运算符进行重载
一 运算符重载的基本使用
运算符重载的本质是以函数的方式来体现 -----> 设计一函数,只不过该函数有一定特征
语法:
返回值 operator(以关键字开头)运算符(或操作符)(参数列表)
{
函数体;
}
对于运算符重载,有 两种方式
1.成员函数进行运算符重载
2.全局函数进行运算符重载
成员函数进行运算符重载
class A
{
public:
A(int a=0):a(a)
{
}
//运算符(+)重载 : + 是一个双目运算符:左操作数 右操作数
//对于成员函数来实现双目运算符,参数只要一个,而不是两个,原因在于,当一个对象调用该成员函数时,隐式传入对象对this
//this ---> 左对象
A operator+(const A& a2)
{
A aa;
aa.a = this->a + a2.a;
return aa;
}
//显示信息
void printA()
{
cout << "a = " << a << endl;
}
private:
int a;
};
int main()
{
A a1(10);
a1.printA();
int i;
int j;
int k = i + j;
//(i + j) = 30; //error
A a2(20);
a2.printA();
A a3 = a1 + a2; //由于C++不提供两个对象之间相加的操作,没有实现运算符(+)功能。但是,它把重载的机制实现开放给类设计者
a3.printA();
A a4 = a1.operator+(a2); // 跟 a1 + a2 两者是等价
a4.printA();
// (a1 + a2) = 100;//ok
return 0;
}
全局函数实现运算符重载
class Point
{
public:
friend Point operator +(const Point& p1,const Point& p2);
Point(int x = 0,int y=0)
{
this->x = x;
this->y = y;
}
//成员函数进行运算符重载时,参数个数至少是0个,具体的个数要跟运算符来制定,运算符:单目运算符 双目运算符 三目运算符
//成员函数中隐含一个this
Point operator +()
{
}
int getX()const
{
return this->x;
}
int getY()const
{
return this->y;
}
private:
int x;
int y;
};
//不管是全局函数还是成员函数,运算符重载函数名是固定的
//全局函数做为运算符重载函数时,参数个数至少要一个,具体的个数要跟运算符来制定
Point operator +(const Point& p1,const Point& p2)
{
Point temp;
temp.x = p1.x + p2.x;
temp.y = p1.y + p2.y;
return temp; //在返回时,会调用默认的拷贝构造函数
}
int main()
{
Point p1(1,2);
Point p2(3,4);
//方法一 成员函数进行 + 重载
//方法二 全局函数进行+ 重载
Point p3 = p1 + p2;
cout << p3.getX() << "===" << p3.getY() << endl;
int i;
cout << i;
return 0;
}
流输出运算符重载
int i;
cout << i;
Point p;
cout << p; //默认情况下,不能
全局函数实现<<运算符重载
//全局函数来实现<<重载
//从系统中,发现
//typedef basic_ostream<_CharT, _Traits> __ostream_type;
/*__ostream_type&
operator<<(long long __n)
{ return _M_insert(__n); }*/
// typedef basic_ostream<char> ostream;
ostream& operator <<(ostream& os,const Point& p1)
{
// os << "(" << p1.getX() <<"," << p1.getY() << ")" << endl; //ok
cout << "(" << p1.getX() <<"," << p1.getY() << ")" << endl;
return os;
}
流输出(<<)和流输入(>>)重载的格式:
//<< 重载
ostream& operator <<(ostream& os,const A& a1)
{
cout << "a = " << a1.a << endl;
return os;
}
// >> 重载 --->如果是输入流重载,那么它的右操作不能使用const修饰
istream& operator >>(istream& is, A& a1)
{
is>>a1.a;
return is;
}
左操作数分别固定为: ostream 和 istream
右操作数则为输出的类对象
全局函数和成员函数进行运算符重载总结:
对于成员函数和全局函数实现运算符重载
成员函数: L.operator@(R)
全局函数:operator@(L,R)
ostream& operator <<(ostream& os,const Point& p1)
1.对于全局函数来实现运算符重载时,参数一为左操作数(当前类的对象),参数二为右操作数,可以为当前类的一个对象或者不是
所以一个类中如果想要实现对运算符"<<" 和 ">>"重载,使用全局函数来进行重载
2. 当全局函数和成员函数都进行了运算符重载,那么程序优先选择成员函数运算符重载函数,另外,成员函数运算符重载函数
也支持重载
二 重载规则
C语言运算符:
- 可重载的运算符:算术运算符、关系运算符 自增和自增运算符 ,左移和右移运算符
+ - * / % ^ & | ~
! = < > <= >= ++ --
<< >> +=,-= <<= >>=
[] () -> ->* new new[] delete delete[]
2.不能新增运算符,只能对已有C++运算符进行重载
3.不能改变操作数个数
4.不改变语义
不可重载的运算符:
. (成员访问运算符)
.* (成员指针访问运算符)
:: (域运算符)
sizeof (长度运算符)
?: (条件运算符)
//赋值运算符 ----> 系统默认会提供给我们
Complex p3;
p3 = p1; //调用了系统的默认赋值运算符函数,也可以手动自实现
三 运算符重载的应用
数据类的转换:double ---> int 把一个类的对象转换为其他的类型 A --->B
//两个类之间的转换,那么它们还是会存在着某种联系
class A{
};
class Data
{
public:
//数据类型转换的语法:
/*
operator 目标类型()
{
}
*/
#if 1
operator int()
{
return data;
}
#endif
operator A()
{
return a;
}
private:
int data;
double number;
char c;
A a;
};
int main()
{
Data myData;
int a = myData;
A d = myData; //将数据类型Data转换成A
//以QT中字符串就是通过这种原理来实现
/*
//将long int uint ulong doule ---> QString
number(long , int ) : QString
number(int , int ) : QString
number(uint , int ) : QString
number(ulong , int ) : QString
number(qlonglong , int ) : QString
number(qulonglong , int ) : QString
number(double , char , int ) : QString
//将QString ---> double float int
toDouble(bool *) const : double
toFloat(bool *) const : float
toInt(bool *, int ) const : int
*/
return 0;
}