【C++第八课】---操作符重载上

一、关于C和C++标准库的使用

我们都知道C++为了向下兼容C,和多库都是基于C来开发的,那么对于C++的库的使用需要注意什么地方呢?

1、C++标准库并不是C++语言的一部分
2、C++ 标准库是由C++语言编写而成的类库和函数的集合 
3、C++标准库中定义的类和对象都位于std命名空间中 
4、C++标准库的头文件都不带.h 后缀
5、C++ 标准库涵盖了C库的功能
6、C库中<name.h>头文件对应 头文件对应C++ 中的<cname>

7、C++标准库预定义了多数常用的数据结构,如:字符串, 链表,队列,栈等。

下面举两个例子说明使用C库和C++库的区别

#include <cstdio>		//使用C++标准库

int main(int argc,char** argv)
{
	printf("This is a example !!\n");
	return 0;	
}

#include <iostream>		//使用C++标准库

using namespace std;

int main(int argc,char** argv)
{
	cout<<"This is a example !!"<<endl;
	return 0;	
}


二、利用操作符的重载实现复数的加减

实例一----函数实现复数加法

#include <iostream>

using namespace std;

struct Complex
{
	int a;
	int b;
	Complex(int i = 0,int j = 0)
	{
		a = i;
		b = j;	
	}
};

Complex add(const Complex& c1,const Complex& c2)
{
	Complex ret;
	ret.a = c1.a + c2.a;
	ret.b = c2.b + c2.b;
	return ret;	
}
int main(int argc,char** argv)
{
	Complex a(1,2);
	Complex b(1,2);
	Complex c = add(a,b);
	cout<<"c.a = "<<c.a<<endl;
	cout<<"c.b = "<<c.b<<endl;
	return 0;	
}



说明:上述使用常引用的两个好处

1.能够提升代码执行效率

2.避免被函数体外修改

我们看到上述实现复数相加使用的是函数,那么,我们能不能直接用‘+’来实现呢?当然是肯定的,这里就引入函数的重载了。

操作符的重载实质上就是函数的重载,那么。我们如何利用函数重载来实现操作符的重载呢?

1、C++中通过operator关键字可以利用函数扩展操作符
2、operator的本质是通过函数重载实现操作符重载

下面请看我们函数如何修改

Complex operator+ (const Complex& c1,const Complex& c2)
{
	Complex ret;
	ret.a = c1.a + c2.a;
	ret.b = c2.b + c2.b;
	return ret;	
}


这时候我们得到一个这样的程序:

#include <iostream>

using namespace std;

struct Complex
{
	int a;
	int b;
	Complex(int i = 0,int j = 0)
	{
		a = i;
		b = j;	
	}
};

Complex operator+ (const Complex& c1,const Complex& c2)
{
	Complex ret;
	ret.a = c1.a + c2.a;
	ret.b = c2.b + c2.b;
	return ret;	
}
int main(int argc,char** argv)
{
	Complex a(1,2);
	Complex b(1,2);
	Complex c = a + b;
	cout<<"c.a = "<<c.a<<endl;
	cout<<"c.b = "<<c.b<<endl;
	return 0;	
}



此时的代码和上面的程序红色部分为改动部分,但是当我们编译运行后,能够得到相同的结果,到这里为止,我们就初步的实现了操作符的重载

下面我们还可以对其进行改进!

三、operator操作能够作用类么?

这个问题的答案是肯定的。下面我们改进一下,将struct改为标准的class,代码如下:

#include <iostream>

using namespace std;

class Complex
{
private:
	int a;
	int b;
public:
	Complex(int i = 0,int j = 0)
	{
		a = i;
		b = j;	
	}
friend Complex operator+ (const Complex& c1,const Complex& c2);
friend void print(const Complex& c);
};
void print(const Complex& c)
{
	cout<<"c.a = "<<c.a<<endl;
	cout<<"c.b = "<<c.b<<endl;		
}
Complex operator+ (const Complex& c1,const Complex& c2)
{
	Complex ret;
	ret.a = c1.a + c2.a;
	ret.b = c2.b + c2.b;
	return ret;	
}
int main(int argc,char** argv)
{
	Complex a(1,2);
	Complex b(1,2);
	Complex c = a + b;
	print(c);
	return 0;	
}




注意上面红色部分,我为了能够访问到私有成员,定义了两个友元函数,这样打印的结果与上述程序最终的打印结果是一样的

但是相信大家会发现这种方法比较复杂,需要定义两个友元函数(注意:友元函数不是成员函数),那么我们有没有改进的方

法呢?  

简单,这里我们对<<左移操作符进行重载就行

四、如何对左移操作符进行重载呢?

首先,我们得明白左移右移的参数和对应的表达式是怎样的。

例如:

表达式:cout<<a<<endl;

函数    :ostream& operator<< (ostream& out,const Complex& c)

那么 cout就是对应的第一个参数,a就表示第二个参数。

等价于 ==  operator<<(cout,a);   

请仔细分析为什么返回值为ostream &类型。

具体实例如下:

#include <iostream>

using namespace std;

class Complex
{
private:
	int a;
	int b;
public:
	Complex(int i = 0,int j = 0)
	{
		a = i;
		b = j;	
	}
friend Complex operator+ (const Complex& c1,const Complex& c2);
friend ostream& operator<< (ostream& out,const Complex& c);
};
Complex operator+ (const Complex& c1,const Complex& c2)
{
	Complex ret;
	ret.a = c1.a + c2.a;
	ret.b = c2.b + c2.b;
	return ret;	
}
ostream& operator<< (ostream& out,const Complex& c)
{
	out<<c.a<<" + "<<c.b<<"i";
	return out;
}

int main(int argc,char** argv)
{
	Complex a(1,2);
	Complex b(1,2);
	Complex c = a + b;
	cout<<a<<endl;
	cout<<b<<endl;
	cout<<c<<endl;
	return 0;	
}



打印内容如下:

1 + 2i
1 + 2i
2 + 4i

 五、再次引入问题

通过operator operator关键字能够将操作符定义为全局函数,而操作符重载的本质就是函数重载

那么,类的成员函数是否可以作为操作符重载的函数呢?

答案是肯定的。

类成员函数实现操作符重载的一个实例

Complex Complex::operator+ (const Complex& c2)
{
	Complex ret;
	ret.a = a + c2.a;
	ret.b = b + c2.b;
	return ret;	
}



千万千万要注意的是:

1、用成员函数重载的操作符比全局操作符重载函数少一个参数,即左操作数。
2、不需要使用friend关键字  

否则会报错。

这是为什么呢?

因为第一个参数会调用this指针,用this指针指向成员变量的。

所以如下程序也是没有问题的

#include <iostream>

using namespace std;

class Complex
{
private:
	int a;
	int b;
public:
	Complex(int i = 0,int j = 0)
	{
		a = i;
		b = j;	
	}
Complex operator+ (const Complex& c2);
friend ostream& operator<< (ostream& out,const Complex& c);
};
Complex Complex::operator+ (const Complex& c2)
{
	Complex ret;
	ret.a = a + c2.a;
	ret.b = b + c2.b;
	return ret;	
}
ostream& operator<< (ostream& out,const Complex& c)
{
	out<<c.a<<" + "<<c.b<<"i";
	return out;
}

int main(int argc,char** argv)
{
	Complex a(1,2);
	Complex b(1,2);
	Complex c = a + b;
	cout<<a<<endl;
	cout<<b<<endl;
	cout<<c<<endl;
	return 0;	
}



还有一个需要注意的地方:

1、当无法修改左操作数的类时,使用全局函数进行重载
2、=, [], ()和->操作符只能通过成员函数进行重载
待续。。







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值