Lesson 20 运算符重载
来源:互联网 发布:linux测试dns解析命令 编辑:程序博客网 时间:2024/06/08 09:55
多态:同一种形为,不同的对象得到不同的结果;(按这里的定义来看,不一定是函数,可以是运算符) //运算符应该是重载,多态才是覆盖,重载不能算 是多态;上面的辩证法可能 有问题??
静态多态(运算符重载,函数重载)
一、运算符重载
Complex obj1,obj2,obj3;
obj1 = 3;
obj3 = obj2;
obj3 = obj1 + obj2;
cout<< obj1<<obj2<<endl;
上面的运算符,默认情况下是无法实现的,因此需要为自定义的类实现自己的运算符;
运算符重载:对已有的功能赋以其另一种功能,以适用于不同的数据类型;
重载不能修改优先级和结合性!重载的功能应与原功能相似;
不可以重载的运算符有: . .* :: ?:
运算符重载可以通过定义类的成员函数或是友元函数实现
成员函数重载运算符:
返回类型 类名::operator运算符(形参列表)
{
}
<span style="font-size:24px;">complex operator+(const complex& m) const; </span>
<span style="font-size:24px;"><span style="color:#ff0000;">//这里用2个const 是因为外面的const修饰thist,并不是说m不可以改变</span>complex a(1,2);complex b(2,3);complex c = a +b; /// 运算符左操作符是调用函数的对象,右操作数是参数 a.operator+(b); </span>
/// 使用成员函数重载运算符,左操作数要求是类本身对象,而右操作数可以为其它类型 如上面参数为int
// 这时可以再次重载,参数传int ,实现 b = a + 3;
显然,成员函数无法实现 b = 3 + a
友元全局函数重载运算符:
friend 返回值类型 operator运算符(形参列表) // 二元操作要两个形参,一元操作为空形参列表
{
}
friend complex operator+(const Complex &a, const Complex &b);
// 用友元的意义是为了能访问类的私有成员,如果私有成员都有接口,那可以不用友元
b = 3 + a是可以用全局函数实现!
建议:二元操作用友元全局函数实现; 如果第一个操作数要求是本类对象,推荐用成员函数,如果第一 个数肯定不是本类对象,推荐用友元函数实现
特定的运算符:
1. 只能用成员函数实现的运算符:(第一个操作数一定要是本类对象)
= , (), [ ], -> :如= 如果用a = b ,则本类对象是a,b = a 的本类对象是b;a 与b 的类型可能不同;
2. 只能使用友元函数实现的:(第一个操作数一定不是本类对象)
>> , << (输入输出)
二、常用运算符重载
单目:++, -- //推荐使用成员函数
++a;
成员函数:
Complex & operator++() // 返回必须是本类对象的引用,返回引用则可以作左值: ++a = 3; // a = 3;
{
++m_real;
++m_imag;
return *this; // 左值看成返回本身
}
a++;
Complex operator++ (int) // int 没有任何意义
{
Complex temp(*this);
++m_real;
++m_imag;
return temp;
}
友元全局函数:
Complex &operator--(Complex& a) // --a;
{
a.m_real ++;
a.m_imag ++
return ax;
}
双目运算符:
1. >> 、<<
cout<<a; cin>>a; 第一个操作数都不是本类对象;因此要用到友元全局函数;
cout << a << b; // 说明返回值是可以做左值的,即要返回引用ostream类型;
friend istream& operator>>(istream& in, 用户类型& obj) // obj用&可以不用干枯析内存
{
in >> obj.x;
in >> obj.y;
return in;
}
friend ostream & operator<<(ostream& out, const 用户类型& obj)
{
out<<obj.x;
return out;
}
cin>>a>>b; // operator>>((operator(cin,a)),b);
2. 赋值运算符重载
// 当类要定义析构函数(指针成员被删2次)的时候要定义拷贝构造函数(深拷贝)与=运算符重载
Complex& operator=(const Complex& ref);
=运算符只能定义成成员函数重载,即即一个操作数必须为类对象;
=不定义系统会生成一个默认的,这会造成浅拷贝的问题;
在子类中要显式的调用直接基类的=运算符!!!
class A
{
int a;
};
class B:public A
{
int b;
};
B& operator=(B& ref) // 有两部分要赋值:A类中的a,B类中的b;
{
A::operator=(ref); // 子类赋给A类
b = ref.b;
return *this;
}
com a;
com b = a; // 初始化拷贝构造函数
com c;
c = a; // =运算符重载
3. 下标运算符[ ]
TYPE & operator[ ](const int aIndex); // TYPE存储的数据类型
重载new, delete运算符
void 类名::operator delete(void*, [arg_list]);
若有第二个参数,必须为size_t
重载类型转换运算符:
Length obj1(1000);
double m = double(obj1); // double m = obj1.operator double(); 显示调用的结果
m = obj1; // m = obj1.operator double(); //隐示调用
operator<强制转换的目标类型>() // 无参数(只转换自身),无返回值
{
// 定义后,可以显式调用或是隐式调用
}
可以通过构造函数实现类型转换:
Complex(int b);
void foo(Complex com);
int b= 5; foo(b); // b 被转换成了Complex类型
operator int(); // 强制类型转换
上面两个红色的过程,都完成了类型转换,同时转换会出现二义性!即foo(b);不知道调用 哪个函数完成类型转换
总结
1. 赋值运算符重载; com = coo; // com.operator=(const Coordinate& coo);
2. 构造函数; com = coo; // 先调用Complex::Complex(const Coordinate& coo);再用赋值运算符=赋给com
3. 类型转换运算符(); com = coo; // 在Coordinate类中实现: operator Complex() const; 先调用Coordinate类中的类型转换运算符,再调用Complex类的赋值运算符
#ifndef TEST#define TEST#include <iostream>#include <string>using namespace std;class B;class A;extern ostream& operator<<(ostream& in,const A&a);extern ostream& operator<<(ostream& in,const B&a);class A{public:int x;int y;friend ostream& operator<<(ostream& out,const A&a);A():x(5),y(10){};//A(B& b); // 构造函数完成类型转换A& operator=(const B& b); // 赋值运算符完成类型转换};class B{public:string str1;string str2;B():str1("123.5"),str2("55.5"){};friend ostream& operator<<(ostream& out,const B&a);operator A();};#endif
#include "testmain.h"#include <iostream>#include <string>using namespace std;// 强制类型转换ostream& operator<<(ostream& out, A&a){out << "A的值为:" << a.x<<" "<<a.y;return out;}ostream& operator<<(ostream& out,const B&a){out<<"B: "<<a.str1<<" "<<a.str2;return out;}/*A::A(B& b){cout<<"开始调用构造函数转换B->A:"<<b<<endl;x = atoi(b.str1.c_str());y = atoi(b.str2.c_str());cout<<"构造函数转换成功后:"<<x<<" "<<y<<endl;}*/A& A::operator=(const B& b){cout<<"开始调用赋值运算符转换B->A:"<<b<<endl;x = atoi(b.str1.c_str()) + 1;y = atoi(b.str2.c_str()) + 1;cout<<"赋值运算符转换成功后:"<<x<<" "<<y<<endl;return *this;}B::operator A(){cout<<"开始调用强制类型转换运算符转换B->A"<<endl;A a;a.x = atoi(str1.c_str()) + 10;a.y = atoi(str2.c_str()) + 10;cout<<"强制类型转换运算符转换成功后:"<<a.x<<" "<<a.y<<endl;return a;}int main(){A a;B b;cout<<b<<endl;cout<<a<<endl;a = b;cout<<"_____________________"<<endl;B c;a = A(c);cout<<a<<endl;}
- Lesson 20 运算符重载
- 运算符重载 [++,--,+,<<; &&,||(不可重载)]
- 重载之运算符重载
- C++学习20:运算符重载
- 重载赋值运算符
- C++运算符重载
- 运算符重载
- 运算符重载总结
- 运算符重载例子
- 运算符重载
- 运算符重载
- 基础:运算符重载
- 运算符重载
- 运算符重载
- 重载赋值运算符
- C#运算符重载
- C++-运算符重载
- 重载赋值运算符
- 【数据库~】SQL Server中Schema(架构)概念理解
- 利用Jquery给当前页或者跳转后页面的导航栏添加选中后样式
- HDU 4960 Another OCD Patient
- c语言笔记
- Android -- NDK开发入门
- Lesson 20 运算符重载
- HDU - 4961 Boring Sum
- The Ubuntu Install By USB
- QDrag简介
- InsertionSort
- ubuntu kugou音乐桌面版
- java ssh环境搭建
- java学习之嵌套循环
- 说一下你眼中的Android的优点和不足之处(面试华为的人有被问过)!!!