运算符重载
认识
由来:对象不能相加 类里面多个成员,不知道谁加谁
而运算符重载就可以使对象相加,运算符可自定义
1.关键字:operator
2.本质是函数
例如:
class Cstu
{
public:
int a;
float b;
Cstu()
{
a = 12;
b = 12.5;
}
};
//运算符重载
void operator+(Cstu &stu,int c) //加上引用,避免拷贝构造
//假如成员stu与12相加 参数列表内是相加的两个数
{
//可自定义类内的哪个成员和c相加
cout << (stu.a + c) << endl;
}
int main()
{
Cstu stu;
stu + 12; //调用运算符重载的函数
//与参数列表里参数的位置对应
system("pause");
return 0;
}
注意:
(1)参数必须有一个包含类的参数或类类型的形参 加上&避免拷贝构造
(2)可以重载
返回值
1.作用:可以进行连续运算
//调用时stu + 12 是两个参数,连续运算就要返回值了
stu + 12 + 13;
代码如下:
int operator+(int d, Cstu&stu)
{
return (12 + stu.a); //将相加的作为int值输出
}
//主函数调用
cout << (12 + stu.a + 13) << endl; //int 值就可以加13了
当有多个运算符重载函数时
int operator+(Cstu& stu, int c)
{
return (stu.a + c);
}
int operator+(int d, Cstu&stu)
{
return (d + stu.a);
}
Cstu& operator+(Cstu&stu, Cstu&stu1)
{
stu.a += stu1.a; //stu里的a进行改变
return (stu );
}
//主函数输出
cout << 12 + stu.a + 13 + (stu1 +stu) + stu1; //连续输出
注意:输出时可以用优先级进行改变,不过要注意能否进行相加
运算符在类内重载
1.类内只写一个整数就可以
原因:参数有隐含的this指针,指向函数外类内的内容 即类+a
而如果用a+类,类内的运算符重载函数就实现不了了
class Cstu
{
public:
int age;
Cstu()
{
age = 12;
}
int operator+(int a) //类内只写一个整数就可以
//原因:1.参数有隐含的this指针,指向函数外类内的内容 即类+a
{
return (age + a);
}
};
注意:
1.类内的运算符重载,左操作数必须是对象,a+类 只能写类外
2.只能重载有效的运算符,例如@就不能重载
3.下面是能重载的注意点
a.=、[]、()、->必须是成员
b.复合赋值运算符,通常是成员:+=、-=、<<(右移)
c.改变对象状态的运算符,如递增,解引用,通常是成员(因为int a;a++;
这样的系统已经定义好了)
d.算术,关系,位运算符,最好非成员
运算符重载例子
算术运算符:+、-、*、%、/
关系运算符:!=、==、<=、>=
位运算符:^、&、|
逻辑运算符:&&、||
二元运算符
class Cstu
{
public:
int a;
Cstu(int age)
{
a = age;
}
};
int operator >= (Cstu &stu1,Cstu &stu2)
{
return (stu1.a >=stu2.a );
}
//主函数调用
Cstu stu1(12);
Cstu stu2(13);
cout << (stu1.a >= stu2.a);
一元运算符
!,+,-,&,*,~等
class Cstu
{
public:
int a;
Cstu(int age)
{
a = age;
}
};
int operator - (Cstu stu3)
{
return(-stu3.a);
}
//主函数调用
cout << (-stu3.a );
输入输出运算符重载
cin,cout也是对象
cin是istream的对象
cout是ostream的对象
ostream
参数一是ostream引用,参数二是对象的常引用
class Cstu
{
public:
int age;
Cstu()
{
age = 12;
}
};
void operator << (ostream &out, Cstu &stu)
{
out << stu.age ;
}
//主函数调用
Cstu stu;
cout << stu; //cout赋给out,stu赋给stu执行函数
但如果想要连续输出
cout << stu << stu;
就要有返回值了
过程:
先调用左边的cout << stu
返回了void,再执行右边时就成了void <<stu;
所以就要用ostream&
来作为返回值,返回定义的输出out
就可以了
代码如下:
ostream& operator << (ostream &out, Cstu &stu)
{
out << stu.age ;
return out; //这样就可以连续输出了
}
注意:
(1)由于左侧是ostream 所以不能放类内
(2)由于数据成员一般都是私有的所以就要借助友元
常用的成型代码如下:
#include<iostream>
using namespace std;
class Cstu
{
private: //数据成员私有
int age;
public:
Cstu()
{
age = 12;
}
//友元使运算符重载函数可见
friend ostream& operator << (ostream &out, Cstu &stu);
};
ostream& operator << (ostream &out, Cstu &stu)
{
out << stu.age ;
return out;
}
int main()
{
Cstu stu;
cout << stu;
system("pause");
return 0;
}
istream
#include<iostream>
using namespace std;
class Cstu
{
private:
int a;
float b;
public:
Cstu()
{
a = 0;
b = 0.0f;
}
void print()
cout << a <<' ' << b;
friend istream& operator >> (istream& in, Cstu &stu);
};
istream& operator >> (istream& in, Cstu &stu)
{
in >> stu.a >> stu.b; //输出
if (in.fail()) //检测是否输入失败
//可以写一个if判断 进到in.fail里,返回的是1
{
//这里面主要的作用是将输错的数据赋一个初始值
// 因为不赋值的话,下面还可能会有更多的错误
stu.a = 0;
stu.b = 0;
}
return in;
}
int main()
{
Cstu stu;
cin >> stu;
stu.print();
system("pause");
return 0;
}
与ostream
的异同:
1.多了一个检测是否输入失败,目的是防止导致更多的错误
2.只能在类外重载,若在类内要写友元
赋值运算符重载
两种:(二元运算符)
1.‘=’
2.符合赋值运算符:+=,-=,/=,%=,<<=,^=,&=,|=等等。
上面说过
=、[]、()、->必须是成员
class Cstu
{
private:
int a;
public:
Cstu()
{
a = 12;
}
void print()
{
cout << a << endl;
}
void operator = (int b)
{
a = b;
}
};
//主函数调用
Cstu stu;
stu = 13;
stu.print();
“+=”赋值运算符的重载
//类内赋值
int operator += (int d)
{
c += d;
return c;
}
//类外赋值运算符重载
Cstu& operator += (Cstu &stu1,int &c)
{
stu1.a += c;
return stu1;
}
//主函数调用
stu1.a += 12;
cout << stu1.a << endl; //外+=
stu.print(); //内+=
下标运算符的重载
注意:
1.返回值引用
若不返回引用则在下面stu[1] = 14;
左边仅是一个值不是变量,就会报错
可以通过指针取地址来解决
2.对象指向了元素后,可以修改值
#include<iostream>
using namespace std;
class Cstu
{
public:
int a = 11;
int b = 12;
int c = 13;
int& operator [](int n)
{
switch (n)
{
case 0:
return a;
case 1:
return b;
}
return c; //都没有返回c
}
};
int main()
{
Cstu stu;
cout << stu[1] << endl; //重载调用的形式
stu[1] = 14; //可以修改值
cout << stu[1] << endl;
system("pause");
return 0;
}
利用指针:
void*operator[]()
通用类指针:
(1)即可以接受任何类型的指针,也可以可往任意类型去转,也能给任何类型的变量赋值(强转)
(2)无具体大小
void*operator[](int n)
{
switch (n)
{
case 0:
return &a;
case 1:
return &b;
}
return &c;
}
//主函数调用
Cstu stu;
cout << *(int*)stu[1] << endl;
递加递减运算符重载
原理和之前的都差不多
前置++:
类外:
class Cstu
{
public:
int a;
Cstu()
{
a = 12;
}
};
int operator ++(Cstu &stu)
{
return (++stu.a ); //返回的是int型
}
//主函数调用
Cstu stu;
cout << ++stu.a << endl;
类内:
public:
int a;
Cstu()
{
a = 12;
}
int operator ++() //没有参数
{
return (++a);
}
};
前置- -同上
后置++:
类外:
class Cstu
{
public:
int a;
Cstu()
{
a = 12;
}
};
int operator ++ (Cstu&stu, int n) //n是区别前置++的,仅是一个标记
{
int b = stu.a; //b装的自加前的值
stu.a++;
return b;
}
//主函数调用
Cstu stu;
cout << stu++ << endl; //调用 自加前的值
cout << stu.a<< endl; //自加后的值
后置- - 同上
重载类型转换
利用强转,是无法将对象转换为int型的
Cstu stu;
(int)stu;
这就用到重载类型转换
形式如下:
class Cstu
{
public:
int a;
double b;
Cstu()
{
a = 12;
b = 12.12;
}
operator int() //对象转int就是这个形式 无返回值
{
return a;
}
operator int()
{
return b;
}
};
//主函数调用
Cstu stu;
cout << (int)stu <<(double)stu << endl;
//也可以写成:stu(int)
注意:
1.没有返回类型,但要写返回值
2.没有参数
3.必须定义成类成员函数
4.不应对内容进行修改,定义成常函数
operator int() const