operator overloading(操作符重载,运算符重载)

所谓重载就是重新赋予新的意义,之前我们已经学过函数重载,函数重载的要求是函数名相同,函数的参数列表不同(个数或者参数类型)。操作符重载也叫运算符重载,顾名思义,运算符重载就是给运算符赋予新的意义,新的使命。

1、首先要说的是,c++中不允许用户自定义运算符,只允许程序员重载运算符。

2、那些运算符可以重载?c++中绝大部分与运算符允许重载,不能重载的运算符有5类,

(1) . (成员访问运算符)。(2).* (成员指针运算符)(3)::(域运算符)

(4)sizeof (长度运算符(5):?(条件运算符/三目运算符)

3、操作符重载的意义,由于c++中不允许用户自定义运算符,所以操作符重载可以满足用户自定义的类型之间的操作运算。比如对象之间的加减乘除等操作。

4、重载运算符的规则。

(1)、重载不能改变运算符运算对象的个数(即操作数的个数)

(2)、重载不能改变运算符的优先级。

(3)、重载不能改变运算符的结合性。

(4)、重载运算符的函数不能有默认的参数,否则就改变了运算符参数的个数,与前面第(3)点矛盾。

(5)、重载的运算符必须和用户定义的自定义类型的对象一起使用,其参数至少应有一个是类对象(或类对象的引用)。也就是说,参数不能全部是C++的标准类型,以防止用户修改用于标准类型数据的运算符的性质。

(6)、用于类对象的运算符一般必须重载,但有两个例外,运算符“=”和“&”不必用户重载。

         ① 赋值运算符(=)可以用于每一个类对象,可以利用它在同类对象之间相互赋值。(这样的拷贝是浅拷贝(logical copy),如果
     成员变量有指针的话,这样的拷贝会造成二次删除,如果要避免二次删除,那么就有必要重载 = 运算符了)

         ② 地址运算符&也不必重载,它能返回类对象在内存中的起始地址。

② *也不必重载,它能返回类对象在内存中的起始地址。

(7)、应当使重载运算符的功能类似于该运算符作用于标准类型数据时所实现的功能。

(8)、运算符重载函数可以是类的成员函数(如例10.2),也可以是类的友元函数,还可以是既非类的成员函数也不是友元函数的普通函数。


Eg:友元函数重载加减乘除(+ - * /)重载

#include<iostream>

#include<stdlib.h>

using namespace std;



class Complex

{

public:

    Complex(float r=0,float i =0):_r(r),_i(i)

        {

        }

        void print() const

        {

                cout<<" _r "<<_r<<" _i "<<_i<<endl;

        }

private:

        float _r;

        float _i;



friend const Complex operator+(const Complex & x,const Complex & y);

friend const Complex operator-(const Complex & x,const Complex & y);

friend const Complex operator*(const Complex & x,const Complex & y);

friend const Complex operator/(const Complex & x,const Complex & y);

friend ostream & operator<<(ostream & out,const Complex & y);

};

inline const Complex operator+(const Complex & x,const Complex & y)

{

        return Complex(x._r+y._r,x._i+y._i);

}

inline const Complex operator-(const Complex & x,const Complex & y)

{

        return Complex(x._r-y._r,x._i-y._i);

}

inline const Complex operator*(const Complex & x,const Complex & y)

{

        return Complex(x._r*y._r-x._i*y._i,x._r*y._i+x._i*y._r);

}

inline const Complex operator/(const Complex & x,const Complex & y)

{

        if(y._r==0 && y._i==0)

        {

                exit(1);

        }

        float den=y._r*y._r+x._i*y._i;

    return Complex((x._r*y._r+x._i*y._i)/den,(x._i*y._r-x._r*y._i)/den);

}

inline ostream & operator<<(ostream & out,const Complex & x)

{

        out<<" -r "<<x._r<<endl;

        out<<" _i "<<x._i<<endl;

        return out;

}



int main()

{

        Complex x(2,3),y(-1,3);

        cout<<" x is ";

        x.print();

        cout<<" y is ";

        y.print();



        (x+y).print();

        operator+(x,y).print();

        (x-y).print();

        operator-(x,y).print();

        (x*y).print();

        operator*(x,y).print();

        (x/y).print();

        operator/(x,y).print();





        cout<<"=================="<<endl;

        operator<<(cout,x);

        (cout<<x)<<"______________"<<endl;

        return 0;



}


成员函数 + - * / 操作符重载

Eg:c成员函数重载加减乘除(+ - * /)重载

#include<iostream>

#include<stdlib.h>

using namespace std;



class Complex

{

public:

        Complex(float r=0,float i =0):_r(r),_i(i)

        {

        }

        void print() const

        {

                cout<<" _r "<<_r<<" _i "<<_i<<endl;

        }

private:

        float _r;

        float _i;

public:

const Complex& operator+(const Complex & y);

const Complex& operator-( const Complex & y);

const Complex& operator*(const Complex & y);

const Complex& operator/(const Complex & y);

};

inline const Complex& Complex::operator+(const Complex & y)

{

        this->_r=_r+y._r;

        this->_i=_r+y._i;

        //(_r+y._r,_i+y._i)

        return (*this);

}

inline const Complex& Complex::operator-( const Complex & y)

{

        return Complex(_r-y._r,_i-y._i);

}

inline const Complex& Complex::operator*( const Complex & y)

{

        return Complex(_r*y._r-_i*y._i,_r*y._i+_i*y._r);

}

inline const Complex& Complex::operator/( const Complex & y)

{

        if(y._r==0 && y._i==0)

        {

                exit(1);

        }

        float den=y._r*y._r+_i*y._i;

        return Complex((_r*y._r+_i*y._i)/den,(_i*y._r-_r*y._i)/den);

}

int main()

{

        Complex x(2,3),y(-1,3);

        cout<<" x is ";

        x.print();

        cout<<" y is ";

        y.print();

        (x.operator+(y)).print();

        

        

        (x+y).print();

        cout<<" x is ";

        x.print();

        cout<<" y is ";

        y.print();

        return 0;



}


>> 输入操作符重载

Eg:>> 输入操作符重载

#include<iostream>

#include<stdlib.h>

using namespace std;



class Complex

{

public:

        Complex(float r=0,float i =0):_r(r),_i(i)

        {

        }

        void print() const

        {

                cout<<" _r "<<_r<<" _i "<<_i<<endl;

        }

private:

        float _r;

        float _i;



friend istream& operator>>(istream &in, Complex& x);

friend ostream& operator<<(ostream &out,const Complex&x);

};

istream& operator>>(istream &in, Complex& x)

{

        in>>x._r>>x._i;

        return in;

}

ostream& operator<<(ostream &out,const Complex&x)

{

        out<<" _r = "<<x._r<<endl;

        out<<" _i = "<<x._i<<endl;

        return out;

}

int main()

{

        Complex x(2,3),y(-1,3);

        x.print();

        Complex d;

        cin>>d;

        //operator>>(cin,x);

        x.print();

        return 0;



}

浅拷贝(logical
copy)  vs  深拷贝(physical copy)


//Eg:浅拷贝
#include<iostream>
#include<string.h>
#define MAX_CHAR 10
using namespace std; class Account
{
public:
Account(char* name="unknown",char* mr="Miss",float f=0.0)
{
title=new char[strlen(name)+1];
strcpy(title,mr);
strcpy(owner,name);
balance=f;
}
            //这里并没有实现深拷贝。只是一个普通的函数,但是这里的思想和重载操作符 = 是一样的,都是单独开辟一段新的             //空间,然后再进行拷贝。~~~~

	    void changetitle(char* newname)
{
if(strlen(newname)>strlen(title))
{
char* tmp=title;
title=new char[strlen(newname)+1];
strcpy(title,newname);
delete []tmp;
}
else
{
strcpy(title,newname); }
}
void changename(char* newname)
{
strcpy(owner,newname);
}
~Account()
{
delete []title;
title=NULL; }
private:
char* title;
char owner[MAX_CHAR];
float balance; friend ostream& operator<<(ostream & os,Account & b); };
ostream& operator<<(ostream & os,Account & b)
{
os<<"who:"<<b.title<<" "<<b.owner<<" "<<b.balance<<endl;
return os;
}
int main()
{
Account acc("zhanger gou","Mr",1000);
Account ac1;
cout<<acc;
cout<<ac1;
ac1=acc;
cout<<ac1;
cout<<acc;
ac1.changename("er gou");
cout<<acc;
cout<<ac1;
ac1.changetitle("Re");
cout<<acc;
cout<<ac1; return 0;
}

浅拷贝的两个问题:

1)、两个对象的指针指向同一块空间,改变其中一个,两个都改变。

2)、两个对象的指针指向同一块空间,不知道谁负责释放指向的空间,很容易造成二次删除。

重载操作符 = 

首先判断是不是自拷贝

第二步 删除指针指向的原来的空间

第三步 开辟新的空间

第四步 拷贝内容,注意的是要将所有内容都拷贝一遍,否则的话会遗漏,其他的会被赋值成默认值。

第五步 返回自身 *this

//Eg:深拷贝 
#include<iostream>
#include<string.h>
#define MAX_CHAR 10
using namespace std; class Account
{
public:
Account(char* name="unknown",char* mr="Miss",float f=0.0)
{
title=new char[strlen(name)+1];
strcpy(title,mr);
strcpy(owner,name);
balance=f;
}
void changetitle(char* newname)
{
if(strlen(newname)>strlen(title))
{
char* tmp=title;
title=new char[strlen(newname)+1];
strcpy(title,newname);
delete []tmp;
}
else
{
strcpy(title,newname); }
}
void changename(char* newname)
{
strcpy(owner,newname);
}
~Account()
{
delete []title;
title=NULL; }
private:
char* title;
char owner[MAX_CHAR];
float balance; friend ostream& operator<<(ostream & os,Account & b);
public:
Account& operator=(const Account& a)
{
if(this!=&a)
{
delete[] title;
title=new char[strlen(a.title)+1];
strcpy(title,a.title);
strcpy(owner,a.owner);
balance=a.balance; }
return *this;
} };
ostream& operator<<(ostream & os,Account & b)
{
os<<"who:"<<b.title<<" "<<b.owner<<" "<<b.balance<<endl;
return os;
}
int main()
{
Account acc("zhanger gou","Mr",1000);
Account ac1;
cout<<acc;
cout<<ac1;
ac1=acc;
cout<<ac1;
cout<<acc;
ac1.changename("er gou");
cout<<acc;
cout<<ac1;
ac1.changetitle("Re");
cout<<acc;
cout<<ac1; return 0;
}

[置顶] operator overloading(操作符重载,运算符重载)运算符重载,浅拷贝(logical copy) ,vs, 深拷贝(physical copy)的更多相关文章

  1. [置顶] 运算符重载,浅拷贝(logical copy) ,vs, 深拷贝(physical copy),三大件(bigthree problem)

    一般的我们喜欢这样对对象赋值: Person p1;Person p2=p1; classT object(another_object), or    A a(b); classT object = ...

  2. 运算符重载,浅拷贝(logical copy) ,vs, 深拷贝(physical copy),三大件(bigthree problem)

    一般的我们喜欢这样对对象赋值: Person p1;Person p2=p1; classT object(another_object), or    A a(b); classT object = ...

  3. C# to IL 5 Operator Overloading(操作符重载)

    Every operator overload that we use in C#, gets converted to a function call in IL. Theoverloaded &g ...

  4. [置顶] C++基础之六:运算符的重载

    网上太多有关运算符的重载了,但是写的太过的详细,不适合新手入门,特别是那什么++和--的前增量后增量重载,一元二元运算符重载,特殊运算符,下标运算符,new和delete,甚至是指针运算符的重载,吓退 ...

  5. C++ operator overload -- 操作符重载

    C++ operator overload -- 操作符重载 2011-12-13 14:18:29 分类: C/C++ 操作符重载有两种方式,一是以成员函数方式重载,另一种是全局函数. 先看例子 # ...

  6. C++ 操作符重载实践 & java没有重载操作符的思路

    实践如下: #include <iostream> using namespace std; class Book{ private: int page; public: Book(int ...

  7. C++ 运算符重载二(一元运算符重载)

    //一元运算符重载 #include<iostream> using namespace std; class Point { public: Point(int x,int y){ th ...

  8. C++重载流插入运算符和流提取运算符【转】

    C++的流插入运算符“<<”和流提取运算符“>>”是C++在类库中提供的,所有C++编译系统都在类库中提供输入流类istream和输出流类ostream.cin和cout分别是 ...

  9. 20.C++- "&&","||"逻辑重载操作符的缺陷、","逗号重载操作符的分析

    "&&","||"逻辑重载操作符的缺陷 大家,都知道"&&","||"拥有"短 ...

随机推荐

  1. HDU 5603 the soldier of love 离线+树状数组

    这是bestcorder 67 div1 的1003 当时不会做 看了赛后官方题解,然后翻译了一下就过了,而且速度很快,膜拜官方题解.. 附上官方题解: the soldier of love 我们注 ...

  2. WebService的发布及客户端的调用

    一.目录 1.JAX-WS发布WebService 1.1 创建一个简单的WS 1.2 打包部署和发布 2.CXF+Spring发布WebService 3.客户端的调用方式 二.正文 1. JAX- ...

  3. appium初探问题总结

    自从搭建好环境后,运行一个appdemo各种奇葩问题层出不穷,过后可能觉得是挺简单的问题,但对于初次接触的人来说,有砸电脑的冲动也不为过·这里将自己所遇到的问题记录下来,备忘. 问题一:照着网上的教程 ...

  4. 位图9宫格 BitmapSlice9.jsfl

    /** * Version 1.1, May 4: fixed issue with symbols in library folders. **/ /** * BitmapSlice9 JSFL b ...

  5. 【原】Storm调度器

    Storm入门教程 1. Storm基础 Storm Storm主要特点 Storm基本概念 Storm调度器 Pluggable scheduler(可插拔调度器) Isolation schedu ...

  6. oracle ref游标

    Oracle 系列:REF Cursor 在上文  Oracle 系列:Cursor  (参见:http://blog.csdn.net/qfs_v/archive/2008/05/06/240479 ...

  7. bzoj 2154 Crash的数字表格(莫比乌斯反演及优化)

    Description 今天的数学课上,Crash小朋友学习了最小公倍数(Least Common Multiple).对于两个正整数a和b,LCM(a, b)表示能同时被a和b整除的最小正整数.例如 ...

  8. 有关ftp批量传送文件或文件夹

    以ftp 批量上传文件时 可以用 mput file1 file2 .. 但是这样没传送一个就会问是否传送下一个 ,那么可以使用prompt这个命令.这是个双向开关,执行一次是取消提示,在执行一次是打 ...

  9. hdoj 2151 Worm【动态规划】

    Worm Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  10. CSS区块、浮动、定位、溢出、滚动条

    CSS中区块的使用 CSS中浮动的使用 CSS中定位的使用 CSS中溢出的使用 CSS中滚动条的使用 17.1 CSS中区块的使用 属性名称            属性值                ...