Lesson 20 运算符重载

多态:同一种形为,不同的对象得到不同的结果;(按这里的定义来看,不一定是函数,可以是运算符)  //运算符应该是重载,多态才是覆盖,重载不能算 是多态;上面的辩证法可能 有问题??  

静态多态(运算符重载,函数重载)

一、运算符重载

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 new(size_t, [arg_list]);

形参表中至少含有一个size_t的参数,且必须为第一个参数


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);不知道调用 哪个函数完成类型转换


总结

类型重载方式:

Coordinate coo(2,3);
Complex com(1,2);
com = coo;

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;

}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值