快捷搜索:  汽车  科技

c中运算符种类(中的运算符重载)

c中运算符种类(中的运算符重载)3、函数体:2.2:函数结束前返回实例自身的引用,既*this。1.2:考虑到修饰的形参不能被修改且要能接收隐式产生的临时量,我们要传常引用。2、返回值:2.1:考虑到要能进行连续赋值,我们要传引用,因为如果不传引用的话,传回去第二次赋的值就给了临时量,而且表达式结束时临时量被销毁,不能做到连续赋值。

c中运算符种类(中的运算符重载)(1)

我们在刚开始学面向对象时就了解了C 中的六个默认构造函数,其中有一个就是赋值运算符重载函数,它重载的是赋值运算符,今天我们就对赋值运算符重载函数具体的要求和写法做以总结。其次再举例说明其他的重载函数。

当我们给出一个类的声明时,写赋值运算符函数要考虑三个方面:

1、传参:

1.1:对于操作运算符重载函数要传的参数可以是引用也可以不是引用。但考虑到传引用时不用生成一个临时对象,不用调用拷贝构造函数,效率高,我们选择传引用。

1.2:考虑到修饰的形参不能被修改且要能接收隐式产生的临时量,我们要传常引用。

2、返回值:

2.1:考虑到要能进行连续赋值,我们要传引用,因为如果不传引用的话,传回去第二次赋的值就给了临时量,而且表达式结束时临时量被销毁,不能做到连续赋值。

2.2:函数结束前返回实例自身的引用,既*this。

3、函数体:

3.1:判断自赋值,如果自赋值,直接返回。

3.2:释放自身的资源,防止内存泄漏。

3.3:开辟新的资源,防止同一块内存区域被释放多次,导致程序奔溃。

对于运算符的操作数,编译器只能识别基础的数据类型,如果要使用符合的数据类型(如结构体),则需要对运算符的操作数进行拓展是运算符支持复合数据类型,C 中的运算符重载就解决了这一问题。

运算符函数定义的一般格式如下:

数据类型 operator<运算符符号>(参数列表)

{

<函数体>

}

有一些特殊的运算符不能被重载:域解析符(::),条件运算符(?:),直接成员访问运算符(.),类成员指针引用运算符(.*) sizeof运算符(sizeof)

运算符重载分为类的内部方式和全局方式,同一种运算符,全局和内部方式只能存在一种。当无法修改左操作数的类时,使用全局函数进行重载。

eg:计算虚数

class Complex

{

friend Complex operator (Complex &c1 Complex &c2);

//使用到类的私有变量,需要设为友元函数

friend Complex operator (Complex &c1 int num);

public:

Complex(int a = 0 int b = 0)

{

this->a = a;

this->b = b;

}

void show()

{

printf("%d %di\n" a b);

}

Complex add(Complex &c)//Complex add(Complex*const this Complex &c)

{

Complex tmp(a c.a b c.b);

return tmp;

}

Complex operator-(Complex &c)//Complex operator-(Complex*const this Complex &c)

{

Complex tmp(a-c.a b-c.b);

return tmp;

}

private:

int a;//实部

int b;//虚部

};

//全局方式:加法运算符的重载:对象 对象

Complex operator (Complex &c1 Complex &c2)

{

Complex tmp(c1.a c2.a c1.b c2.b);

return tmp;

}

//全局方式:加法运算符的重载:对象 常量

Complex operator (Complex &c1 int num)

{

Complex tmp(c1.a num c1.b);

return tmp;

}

//全局方式:全局函数重载运算符

int main()

{

Complex c1(1 2) c2(3 4) c3;

cout << "c1 = 1 2i; c2 = 3 4i" << endl;

cout << "全局方式" << endl;

//编译器不知道如何运算自定义类型,所以不允许直接进行运算

//需要自己写运算规则,写执行函数

// 1.编译器发现c1和c2是自定义类型

// 2.它们要进行 运算

// 3.调用函数执行相应的功能: operator (c1,c2)

// 4.如果存在operator (c1,c2)则执行成功,如果不存在则报错

c3 = c1 c2; // operator (c1,c2) 对象 对象

cout << "operator (c1,c2):";

c3.show();

c3 = c1 10; // operator (c1 10) 对象 常量

cout << "operator (c1 10):";

c3.show();

return 0;

}

//内部方式:类的内部成员(函数)

int main()

{

Complex c1(1 2) c2(3 4) c3;

cout << "c1 = 1 2i; c2 = 3 4i" << endl;

cout << "内部方式" << endl;

c3 = c1.add(c2);/* add省略参数c1,因为调用的是c1中的add函数,

对象c1中有this指针可提供c1的地址,

等价于 add(&c1 c2) =====>c1 c2*/

c3 = c2.add(c1);//add(&c2 c1)=====>c2 c1 参数顺序要清楚,在- * /运算时会影响结果

cout << "c3 = c1 - c2" << endl;

c3 = c1 - c2; // c1.operator-(c2) =====> operator-(&c1 c2)

cout << "operator-(&c1 c2):";

c3.show();

cout << "c3 = c2 - c1" << endl;

c3 = c2 - c1; // c2.operator-(c1) =====> operator-(&c2 c1)

cout << "operator-(&c2 c1):";

c3.show();

return 0;

}

运算符重载是类的友元函数是

调用格式:friend <返回类型> operator<运算符>(参数表)

在类外定义:《返回类型》 operator<运算符》(参数表)

友元函数可以调用类的私有成员,相当于类的公有成员

显示的调用:operator (a b)

#include<iostream>

using namespace std;

class A

{

private:

int a b;

public:

A(int x = 0 int y = 0)

{

a = x;

b = y;

}

int geta()

{

return a;

}

int getb()

{

return b;

}

friend A operator (A p A q);

};

A operator (A p A q)

{

A temp;

temp.a = p.a q.a;

temp.b = p.b q.b;

return temp;

}

int main()

{

A ob1(1 2) ob2(3 4) ob3 ob4;

ob3 = ob1 ob2;

ob4 = operator (ob1 ob2);

cout << ob3.geta() << " " << ob3.getb() << endl;

cout << ob4.geta() << " " << ob4.getb() << endl;

system("pause");

return 0;

}

有了以上的掌握,接下来借助一个类CString我们书写 [] == != << >>运算符重载函数

#include<iostream>

#include<string>

using namespace std;

class CString

{

public:

CString()

{

cout<<"CString()"<<endl;

mpstring=new char[1];

cursize=0;

}

CString(char* str)

{

cout<<"CString(char*)"<<endl;

mpstring=new char[strlen(str) 1];

strcpy(mpstring str);

cursize=strlen(str);

}

~CString()

{

cout<<"~CString()"<<endl;

delete[] mpstring;

mpstring=NULL;

}

CString& operator=(const CString& rhs)

{

cout<<"operator="<<endl;

/*

if(this == &rhs)

{

return *this;

}

delete[] mpstring;

mpstring=new char[strlen(rhs.mpstring) 1];

strcpy(mpstring rhs.mpstring);

cursize=rhs.cursize;

return *this;*/

if(this!=&rhs)

{

delete[] mpstring;

mpstring=new char[strlen(rhs.mpstring) 1];

strcpy(mpstring rhs.mpstring);

cursize=rhs.cursize;

}

return *this;

}

bool operator==(const CString& rhs)

{

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

return strcmp(mpstring rhs.mpstring)==0;

}

bool operator!=(const CString& rhs)

{

cout<<"operator!="<<endl;

//return strcmp(mpstring rhs.mpstring)!=0;//方法一

return !(*this==rhs);//方法二

}

char& operator[](int index)

{

cout<<"operator[]"<<endl;

return mpstring[index];

}

private:

char* mpstring;

int cursize;

friend CString operator (const CString& const CString&);

friend ostream& operator<<(ostream& const CString&);

friend istream& operator>>(istream& CString&);

};

CString operator (const CString& lhs const CString& rhs)

/*必须写在类外,因为要满足所有情况,

比如:CString str3=str1 "world";或者CString str4="Hello" str1;*/

{

cout<<"operator "<<endl;

int lhs_len=strlen(lhs.mpstring);

int rhs_len=strlen(rhs.mpstring);

int len=lhs_len rhs_len 1;

//char* str=new char[len];

char str[20]="";

strcat(str rhs.mpstring);

strcat(str rhs.mpstring);

//CString obj(str);

return CString(str);

}

ostream& operator<<(ostream& out const CString& rhs)

{

cout<<"operator<<"<<endl;

out<<rhs.mpstring<<"";

return out;

}

istream& operator>>(istream& in CString& rhs)//输入流要修改,所以不用加const

{

cout<<"operator>>"<<endl;

char p[20];

in>>p;

if(in)

{

delete[] rhs.mpstring;

rhs.mpstring=new char[strlen(p) 1];

strcpy(rhs.mpstring p);

rhs.cursize=strlen(p);

}

return in;

}

int main()

{

CString str1;

CString str2("hello");

CString str3=str2 "world";

CString str4="hello" str2;

str3=str4;

if(str2!=str4)

{

cout<<str4<<endl;

}

if(str3==str4)

{

cout<<str3<<endl;

cout<<str3[0]<<endl;

}

cin>>str1;

cout<<str1<<endl;

return 0;

}

运行结果:

c中运算符种类(中的运算符重载)(2)

猜您喜欢: