重载运算符

输入带有空格的字符串

cin.getline(a[i])

运算符重载的语法

  • 定义一个重载的运算符与定义一个函数类似,只是这个函数的名称必须以operator开头。

运算符重载函数的一般形式为:

类型	类名::operator 重载的运算符(参数表)
{
		函数体
}

 

参数的个数由以下两个因素决定:

  1. 该操作符是一元操作符还是二元操作符。
  2. 重载为成员函数还是友元函数。

 

运算符重载的两种形式

 

运算符重载函数是如何调用的?

 

运算符重载函数作为类的成员函数

 

成员运算符重载函数在类中的声明格式为:
class  X
{   …… 
    <返回数据类型> operator <运算符> (<参数表>);
    ……
};

成员运算符重载函数在类外定义的格式为:
<返回数据类型>  X:: operator <运算符> (<参数表>)
{ 
     <函数体>
}

举例:

class CComplex
{
	public:
	CComplex(double r=0.0,double i=0.0){real=r,imag=i;}
	void print() const;
	CComplex operator++();		//前缀
	CComplex operator++(int);		//后缀
	CComplex operator--();		//前缀
	CComplex operator--(int);		//后缀
};

常对象

 

运算符重载的限制

  • 只能重载已经存在的C++运算符
  • 运算符重载不能改变运算符操作数的个数,优先级和结合性
  • 运算符的操作数必须至少有一个某个类的类对象,否则不能对运算符进行重载
  • 重载运算符不可以使用缺省参数;
  • 除了赋值运算符 = 外,重载运算符可由派生类继承下去;
  • 下列运算符不能重载:   ::            .*    .    ?:    sizeof

 

运算符重载函数作为友元函数

  • 运算符重载函数可以用友元函数的形式来实现。
  • 函数参数的个数与运算符原有操作数个数相同
  1. 第一个参数表示左操作数
  2. 第二个参数表示右操作数
  3. 第一个参数类型为类对象的引用
  • 赋值运算符‘=’、下标运算符‘[]’、成员选择运算符‘->’和函数调用运算符‘()’等不能用友元函数形式重载
友元运算符重载函数在类中的声明格式为:
      class  X
      {  …… 
           friend  <返回数据类型> operator <运算符> (<参数表>);
         ……
      };
友元运算符重载函数在类外定义的格式为:
     <返回数据类型>  operator <运算符> (<参数表>)
      { 
              <函数体>
      } 

 

重载为成员函数与重载为友元函数的比较

“+”重载为成员函数
CComplex   CComplex::operator+(const CComplex&  c)
{
		return CComplex(real+c.real, image+c.image);
}
“+”重载为友元函数
CComplex  operator+(const CComplex&  c1,const CComplex& c2)
{
		return Complex(c1.real+c2.real,  c1.image+c2.image);
}										

 

运算符重载应用

  • 以下运算符经常需要重载:

             1.算术运算符   2.关系运算符

             3.逻辑运算符   4.赋值运算符

             5.下标运算符   6.函数调用运算符

 

特殊运算符的重载

= 运算符的重载

class Complex
{
	public:
	Complex(double r=0.0,double i=0.0){real=r,imag=i;}
	void display();
	Complex& operator=(const Complex& r_c);
};

【*如果类没有定义赋值运算符重载函数,则编译程序会提供缺省的赋值运算符,就是将赋值运算符右边对象的数据域复制给其左边对象的数据成员。】

注意:分配空间

 

重载下标运算符“[ ]”

  • 下标运算符“[ ]”用来取某个向量的某个元素,或直接对向量中某个元素赋值,它被视为一个二元运算符。
  • 下标运算符只能作类成员运算符进行重载,不可作为友元运算符。
  • 重载下标运算符的最大好处是提供一种向量访问的安全方法。

 

重载()运算符

  • 函数调用运算符”()”可以看作一个双目运算符,它的两个操作数分别为函数名和函数参数列表。             f (x,y)        f ()    
  • 函数调用运算符只能采用非静态的成员函数重载。
  • 函数调用运算符重载可以不带或带任意个参数。

举例

数学函数的抽象:f(x,y) = 2x+y


class Function {
public:
   double operator() (double x, double y) const
   {
	   return 2*x+y;
   }
};

int main( ){
    Function fun;
    cout << fun(1.5, 2.2) << endl;
	
	return 1;
}

 

new和delete的重载

例:重载new和delete运算符。
#include <iostream>
using namespace std;
#include <stddef.h>
class memmanager{
public:
	memmanager(){cout<<"default constructor"<<endl;}
	void *operator new(size_t size);
					//分配一块大小为size的内存
	void *operator new(size_t size,char tag);
 					//分配一块大小为size的内存,并且用字符tag赋值
 	void operator delete(void *p);
					//释放指针p所指向的一块内存空间
};
void *memmanager::operator new(size_t size)
{
 	cout<<"new1 operator"<<endl;
	char *s=new char[size];   		//分配大小为size的内存空间
	*s='a';                    		//用字符'a'赋值
	return s;                    		//返回指针
}
void *memmanager::operator new(size_t size,char tag)
{
  	cout<<"new2 operator"<<endl;
  	char *s=new char[size];
  	*s=tag;                    		//用字符tag赋值
  	return s;                   		//返回指针
}
void memmanager::operator delete(void *p)
{
  	cout<<"delete operator"<<endl;
  	char *s=(char *)p;          		//强制类型转换
  	delete[] s;                 		//释放内存空间
} 
void main()
{
 	memmanager *m=new memmanager();
 	delete m;
 	memmanager *m1=new('B') memmanager();
 	delete m1;
}

 

类型之间的转换

C++语言允许的类型转换有4种:

  • 标准类型->标准类型。
  • 标准类型->类类型。
  • 类类型->标准类型。
  • 类类型->类类型。

【标准类型是除class,struct和union类型外的其他所有类型】

对于标准类型,C++语言提供了两种类型转换:

  • 隐式类型转换。
  • 显式类型转换。

举例:

 

自定义类对象的输入输出

  • 插入运算符<<  和  抽取运算符>>的重载
  • 重载插入和抽取运算符只能用访问类的私有成员的友元函数来实现,因为插入和抽取运算符为双目运算符,且运算符的左操作数为流,右操作数为类对象,因而插入和抽取运算符的重载不能以类成员函数形式出现

举例:


class CComplex		//复数类声明
{
	double real;
	double image;
public:
	CComplex(double r=0.0,double i=0.0):real(r),image(i){}
	friend ostream& operator<<(ostream& stream, CComplex &obj);
	friend istream& operator>>(istream&	stream, CComplex &obj);
};

//注意:在oj上,往往需要
// friend ostream& operator<<(ostream& stream, const Complex &obj);


ostream& operator<<(ostream& stream, CComplex &obj)
{
	if (obj.image < 0)
		stream<< obj.real << obj.image << "i"<<endl;
    else if (obj.image > 0)
		stream << obj.real << "+" << obj.image << "i"<<endl;
    else
		stream << obj.real << endl;

	return stream;
}


istream& operator>>(istream& stream, CComplex &obj)
{
	stream>>obj.real;
	stream>>obj.image;

	return stream;
}

int main()
{

    CComplex obj;
    cin>>obj;
    cout<<obj;
    return 1;
}


 

 

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值