资源描述
单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,单击此处编辑母版标题样式,第 四 章,运算符重载,4.1,重载运算符,4.2,自由存储,4.3,类型转换,4.1.1,概述,4.1.2,一元和二元运算符,4.,1.3,用成员,函,数,重载运算符,4.1.4,用友员函数,重载运算符,4.1.5,重载+和-,4.1.6,重载赋值运算符,4.1.7,重载()和 ,4.1,重载运算符,4.1.1,概述,1.运算符重载的需要,运算符重载使得用户自定义的数据以一种更简洁的方式工作,例如:,int,x,y,y=x+y;,matrix m1,m2;/,矩阵类对象,m2=,Madd,(m1,m2);/,调用函数计算两个矩阵的和,complex c1,c2;/,复数类对象,c1=,Cadd,(c1,c2);/,调用函数计算两个复数的和,能表示为,c1=c1+c2;,?,能表示为,m1=m1+m2;,?,4.1.1,概述,2.,C+,中可以被重载的运算符,+-*/%&|,!=+=-=*=/=%=,=&=|=,new newdeletedelete,不能重载的算符,.:*?:#,4.1.1,概述,2.,C+,中可以被重载的运算符,+-*/%&|,!=+=-=*=/=%=,=&=|=,new newdeletedelete,运算符重载后,可以按它的表达方式使用,不能改变它们的优先级,不能改变算符要求的操作数数目,4.1.1,概述,3.运算符重载的语法形式,运算符通过运算符函数重载。,运算符函数是一种特殊的成员函数,语法形式为:,type,X :operator (,参数表,),/,相对于该类定义的操作,4.1.1,概述,3.运算符重载的语法形式,运算符通过运算符函数重载。,运算符函数是一种特殊的成员函数,语法形式为:,type,X :operator (,参数表,),/,相对于该类定义的操作,返回类型,4.1.1,概述,3.运算符重载的语法形式,运算符通过运算符函数重载。,运算符函数是一种特殊的成员函数,语法形式为:,type,X,:operator (,参数表,),/,相对于该类定义的操作,重载该算符的类的类名,4.1.1,概述,3.运算符重载的语法形式,运算符通过运算符函数重载。,运算符函数是一种特殊的成员函数,语法形式为:,type,X :operator,(,参数表,),/,相对于该类定义的操作,要重载的算符,4.1.1,概述,3.运算符重载的语法形式,运算符通过运算符函数重载。,运算符函数是一种特殊的成员函数,语法形式为:,type,X :,operator,(,参数表,),/,相对于该类定义的操作,关键字,4.1.1,概述,3.运算符重载的语法形式,运算符通过运算符函数重载。,运算符函数是一种特殊的成员函数,语法形式为:,type,X :,operator ,(,参数表,),/,相对于该类定义的操作,由关键字和要重载算符组成函数名,4.1.1,概述,3.运算符重载的语法形式,运算符通过运算符函数重载。,运算符函数是一种特殊的成员函数,语法形式为:,type,X :operator (,参数表,),/,相对于该类定义的操作,运算符要求的操作数,4.1.1,概述,3.运算符重载的语法形式,运算符通过运算符函数重载。,运算符函数是一种特殊的成员函数,语法形式为:,type,X :operator (,参数表,),/,相对于该类定义的操作,一个,运算符被重载后,原有意义没有失去,只是,定义了相对一特定类的一个新运算符,重载了,三个算符,/,ex1,三个算符的重载,(,P90-92),#include,class counter,unsigned,int,value;,public:,counter()value=0;,void,operator +,();,void,operator-,();,unsigned,int,operator(),();,;,void counter:,operator+,(),if (value 0)value,-,;,unsigned,int,counter:,operator(),(),return value;,main(),counter my_counter;,for(,int,i=0;i 12;i,+,),my_counter+;,cout,“n my_counter=”,my_counter();,my_counter-,;,my_counter-,;,cout,“n my_counter=”,my_counter(),;,/,ex1,三个算符的重载,(,P90-92),#include,class counter,unsigned,int,value;,public:,counter()value=0;,void,operator +,();,void,operator-,();,unsigned,int,operator(),();,;,void counter:,operator+,(),if (value 0)value,-,;,unsigned,int,counter:,operator(),(),return value;,main(),counter my_counter;,for(,int,i=0;i 12;i,+,),my_counter+;,cout,“n my_counter=”,my_counter();,my_counter-,;,my_counter-,;,cout,“n my_counter=”,my_counter(),;,使用,系统预定义版本,/,ex1,三个算符的重载,(,P90-92),#include,class counter,unsigned,int,value;,public:,counter()value=0;,void,operator +,();,void,operator-,();,unsigned,int,operator(),();,;,void counter:,operator+,(),if (value 0),value-,;,unsigned,int,counter:,operator(),(),return value;,main(),counter my_counter;,for(,int,i=0;i 12;i,+,),my_counter+;,cout,“n my_counter=”,my_counter();,my_counter-,;,my_counter-,;,cout,“n my_counter=”,my_counter(),;,使用,系统预定义版本,/,ex1,三个算符的重载,(,P90-92),#include,class counter,unsigned,int,value;,public:,counter()value=0;,void,operator +,();,void,operator-,();,unsigned,int,operator(),();,;,void counter:,operator+,(),if (value 0),value-,;,unsigned,int,counter:,operator(),(),return value;,main(),counter my_counter;,for(,int,i=0;i 12;,i+,),my_counter+;,cout,“n my_counter=”,my_counter();,my_counter-,;,my_counter-,;,cout,“n my_counter=”,my_counter(),;,使用,系统预定义版本,“,=,”,运算符重载不能被派生类继承,由于重载可以对定义算符新的含义,要注意程序的可读性,例如:用运算符,“,+,”,表示减运算;用,“,*,”,表示除运算,违反程序阅读习惯,注意:,4.1.2,一元和二元运算符,运算符重载时,运算符函数只能定义为两种方式:,类的成员函数,友员函数,这两种方式非常相似,关键区别在于,成员函数,具有,this,指针,友员函数,没有,this,指针,1.一元运算符,一元运算符,不论是前缀还是后缀,都需要一个操作数:,aa,及,aa,重载的运算符,重载的运算符,1.一元运算符,一元运算符,不论是前缀还是后缀,都需要一个操作数:,aa,及,aa,重载算符 的类的对象,重载算符 的类的对象,1.一元运算符,一元运算符,不论是前缀还是后缀,都需要一个操作数:,aa,及,aa,可以解释为:,aa.operator (),或,operator (aa),1.一元运算符,一元运算符,不论是前缀还是后缀,都需要一个操作数:,aa,及,aa,可以解释为:,aa.operator (),或,operator (aa),一元运算符函数,operator,所需的一个操作数由对象,aa,通过,this,指针隐含地传递,因此参数表为空。这时,运算符函,数用类的,成员函数,表示,1.一元运算符,一元运算符,不论是前缀还是后缀,都需要一个操作数:,aa,及,aa,可以解释为:,aa.operator (),或,operator (aa),一元运算符函数,operator,所需的一个操作数在参数表中,由对象显式地提供,适用于没有,this,指针的情况。这时,运算符,函数用类的,友员函数,表示,一元运算符函数,operator,所需的一个操作数由对象,aa,通过,this,指针隐含地传递,因此参数表为空。这时,运算符函,数用类的,成员函数,表示,1.一元运算符,一元运算符,不论是前缀还是后缀,都需要一个操作数:,aa,及,aa,不管用成员函数或用友员函数重载运算符,,对运算符的使用方法都是相同的,2.二元运算符,同样,对任意二元运算符:,aa,bb,可以解释为:,aa.operator (bb),或,operator (aa,bb),2.二元运算符,同样,对任意二元运算符:,aa,bb,可以解释为:,aa.operator (bb),或,operator (aa,bb),二元运算符函数,operator,所需的一个操作数由对象,aa,通过,this,指针隐含地传递。因此它只有一个参数。这时,运算符,函数用类的,成员函数,表示,2.二元运算符,同样,对任意二元运算符:,aa,bb,可以解释为:,aa.operator (bb),或,operator (aa,bb),二元运算符函数,operator,所需的一个操作数由对象,aa,通过,this,指针隐含地传递。因此它只有一个参数。这时,运算符,函数用类的,成员函数,表示,二元运算符函数,operator,所需的两个操作数在参数表中,由对象,aa,和,bb,显式地提供,适用于没有,this,指针的情况。这时,,运算符函数用类的,友员函数,表示,2.二元运算符,同样,对任意二元运算符:,aa,bb,不管用成员函数或用友员函数重载运算符,,对运算符的使用方法都是相同的,4.1.3,用成员函数重载运算符,例:创建一个名为,three_d,的简单类,,three,类含有三维空间,中的一对象坐标。该程序相对于,three_d,类对,“,+,”,和,“,=,”,运算符进行重载。,/,ex2(,例,4-1,P94-96),#include,class three_d,int,x,y,z;/3_d coordinates,public:,three_d operator,+,(three_d t);,/,重载,“,+,”,three_d operator,=,(three_d t);,/,重载,“,=,”,three_d operator,+,();,/,重载,“,+,”,void show();,void assign(,int mx,int,my,int mz,);,;,three_d three_d:operator,+,(three_d t),/,重载,“,+,”,three_d temp;,temp.x=x+t.x;temp.y=y+t.y;temp.z=z+t.z;,return temp;,three_d three_d:operator,=,(three_d t),/,重载,“,=,”,x=t.x;y=t.y;z=t.z;return *this;,three_d three_d:operator,+,(),/,重载一元运算符,“,+,”,x+;y+;z+;return *this;,void three_d:show(),/,显示,x,y,z,坐标,cout,x “,”y “,”z “n”;,void three_d:assign(,int mx,int,my,int mz,),/,指定坐标,x=,mx,;y=my;z=,mz,;,three_d three_d:operator,+,(,three_d t,),/,重载,“,+,”,three_d temp;,temp.x=x+t.x;temp.y=y+t.y;temp.z=z+t.z;,return temp;,three_d three_d:operator,=,(three_d t),/,重载,“,=,”,x=t.x;y=t.y;z=t.z;return *this;,three_d three_d:operator,+,(),/,重载一元运算符,“,+,”,x+;y+;z+;return *this;,void three_d:show(),/,显示,x,y,z,坐标,cout,x “,”y “,”z “n”;,void three_d:assign(,int mx,int,my,int mz,),/,指定坐标,x=,mx,;y=my;z=,mz,;,重载二元算符参数表只明确一个变元,另一个变元用,this,指针隐含传递,three_d three_d:operator,+,(,three_d t,),/,重载,“,+,”,three_d temp;,temp.x=,x,+t.x;temp.y=y+t.y;temp.z=z+t.z;,return temp;,three_d three_d:operator,=,(three_d t),/,重载,“,=,”,x=t.x;y=t.y;z=t.z;return *this;,three_d three_d:operator,+,(),/,重载一元运算符,“,+,”,x+;y+;z+;return *this;,void three_d:show(),/,显示,x,y,z,坐标,cout,x “,”y “,”z x,three_d,three_d:operator,+,(three_d t),/,重载,“,+,”,three_d temp;,temp.x=x+t.x;temp.y=y+t.y;temp.z=z+t.z;,return temp;,three_d three_d:operator,=,(three_d t),/,重载,“,=,”,x=t.x;y=t.y;z=t.z;return *this;,three_d three_d:operator,+,(),/,重载一元运算符,“,+,”,x+;y+;z+;return *this;,void three_d:show(),/,显示,x,y,z,坐标,cout,x “,”y “,”z “n”;,void three_d:assign(,int mx,int,my,int mz,),/,指定坐标,x=,mx,;y=my;z=,mz,;,返回类类型,便于作复杂运算,例如,a+b+c,事实上该函数可以返回任意正确,C+,类型,three_d three_d:operator,+,(three_d t),/,重载,“,+,”,three_d temp;,temp.x=x+t.x;temp.y=y+t.y;temp.z=z+t.z;,return temp;,three_d three_d:operator,=,(three_d t),/,重载,“,=,”,x,=t.x;,y,=t.y;,z,=t.z;return,*this,;,three_d three_d:operator,+,(),/,重载一元运算符,“,+,”,x+;y+;z+;return *this;,void three_d:show(),/,显示,x,y,z,坐标,cout,x “,”y “,”z “n”;,void three_d:assign(,int mx,int,my,int mz,),/,指定坐标,x=,mx,;y=my;z=,mz,;,赋值运算符修改第一个操作数(,this,所指对象),返回对象类型,使得连续赋值合法,a=b=c=d;,three_d three_d:operator,+,(three_d t),/,重载,“,+,”,three_d temp;,temp.x=x+t.x;temp.y=y+t.y;temp.z=z+t.z;,return temp;,three_d three_d:operator,=,(three_d t),/,重载,“,=,”,x=t.x;y=t.y;z=t.z;return *this;,three_d three_d:operator,+,(),/,重载一元运算符,“,+,”,x+;y+;z+;return *this;,void three_d:show(),/,显示,x,y,z,坐标,cout,x “,”y “,”z “n”;,void three_d:assign(,int mx,int,my,int mz,),/,指定坐标,x=,mx,;y=my;z=,mz,;,“,+,”,运算符没有对象明确传送给函数,通过,this,指针隐含传送,main(),three_d a,b,c;,a.assign(1,2,3);,b.assign(10,10,10);,a.show();b.show();,c,=,a,+,b,;,/,将,a,和,b,加在一起,c.show();,c,=,a,+,b,+,c;,/,将,a、b、c,加在一起,c.show();,c,=,b,=,a;,/,多重赋值,c.show();,b.show();,c,+,;,/,对,c,递加,c.show();,程序输出:,1,2,3,10,10,10,11,12,13,22,24,26,1,2,3,1,2,3,2,3,4,表达式引起对算符函数调用的对象是,a,,算符右边的对象,b,作为参数传递给函数,可以解释为,a.operator+(b);,4.1.4,用友员重载运算符,有时候,用成员函数重载运算符会碰到麻烦。例如:,class Complex,int,Real;,int Imag,;,public:,Complex(,int,a)Real=a;,Imag,=0;,Complex(,int,a ,int,b)Real=a;,Imag,=b;,Complex operator+(Complex);,.,;,int,f(),Complex z(2,3),k(3,4);,z=z+27;,z=27+z;,.,4.1.4,用友员重载运算符,有时候,用成员函数重载运算符会碰到麻烦。例如:,class Complex,int,Real;,int Imag,;,public:,Complex(,int,a),Real=a;,Imag,=0;,Complex(,int,a ,int,b)Real=a;,Imag,=b;,Complex operator+(Complex),;,.,;,int,f(),Complex z(2,3),k(3,4);,z=z+27;,/ok,z=27+z;,.,表达式,z+27,可被解释为,z.operator+(27),z,是复数对象,使用,“,+,”,的,重载版本;,由于重载算符函数要求的,右操作数也为复数,系统通过,构造函数,Complex(,int,a),将,整数 27 转换为,Complex,类常,量,Complex(27),4.1.4,用友员重载运算符,有时候,用成员函数重载运算符会碰到麻烦。例如:,class Complex,int,Real;,int Imag,;,public:,Complex(,int,a)Real=a;,Imag,=0;,Complex(,int,a ,int,b)Real=a;,Imag,=b;,Complex operator+(Complex);,.,;,int,f(),Complex z(2,3),k(3,4);,z=z+27;,/ok,z=27+z,;,/error,.,表达式 27+,z,可被解释为,27,.,operator+(z),该式子,毫无意义,。,27不是,Complex,类对象,,不能调用算符重载函数与对象,z,相加,!,此时,成员函数重载的算,符,“,+,”,不支持交换律。,4.1.4,用友员函数重载运算符,在第一个参数需要隐式转换的情形下,使用友员函数重载算符是正确的选择。,由于友员函数没有隐含,this,指针,用友员函数重载算符时,所需操作数都必须在参数表显式声明,所以很容易实现类型的隐式转换。,4.1.4,用友员重载运算符,把重载运算符函数改为友员函数:,class Complex,int,Real;,int Imag,;,public:,Complex(,int,a)Real=a;,Imag,=0;,Complex(,int,a ,int,b)Real=a;,Imag,=b;,friend,Complex operator+(,Complex,Complex,);,.,;,int,f(),Complex z(2,3),k(3,4);,z=z+27;,/ok,z=27+z,;,/ok,.,/,ex3,使用友员函数重载运算符,#,include,class complex,public:,complex(double r=0,double i=0);,void print()const;,friend complex operator+(,const,complex&c1,const,complex,friend complex operator-(,const,complex&c1,const,complex,friend complex operator-(,const,complex,private:double real,imag,;,;,常参数,,函数体内不能修改实际参数,常参数,,函数体内不能修改实际参数,complex:complex(double r,double i )real=r;,imag,=i;,complex operator+(const complex&c1,const complex&c2),double r=c1.real+c2.real;double i=c1.,imag,+c2.,imag,;,return complex(r,i);,complex operator-(const complex&c1,const complex&c2),double r=c1.real-c2.real;double i=c1.,imag,-c2.,imag,;,return complex(r,i);,complex operator-(const complex&c),return complex(-c.real,-c.,imag,);,void complex:print()const,cout,(real “,”,imag,)x+;,opl,-y+;,opl,-z+;return *,opl,;,使用友员的问题,问题,C+,不知道如何激活该函数,下述代码无法编译:,three_d ob(1,2,3);,/error,二义性,对,ob,的地址进行递加?,还是,将对象,ob,递加?,3.使用引用参数,:,three_d three_d:operator+(three_d,&,opl,),opl,.x+;,opl,.y+;,opl,.z+;return,opl,;,使用友员的问题,下述代码是正确的:,three_d ob(1,2,3);,ob+;/ok,可见,如果一个运算符的操作要修改类的对象的状态,要重载为友员函数时,应该使用引用参数,4.1.4,用友员函数重载运算符,若一运算符的操作需要修改类对象状态时,则它应该是成员函数。需要左值操作数的运算符(如=,*=,+)应该用成员函数重载。,定义成友员时要用引用参数。,如果运算符的操作数(尤其是第一个操作数)希望有,隐式转换,则重载算符时必须用友员函数,不能用友员函数重载的运算符是,=(),4.1.5,重载,+,和,-,C,语言中,运算符+和-有两种方式:,前缀方式:,+,i;-i;,后缀方式:,i+;i-;,一元,成员函数,重载:,aa.operator+();,友员函数,重载:,operator+(X&aa),/,其中,aa,是,X,类的对象,二元,成员函数,重载:,aa.operator+(,int,);,友员函数,重载:,operator+(X&aa,int,),这时,,第二个参数(,int,),一般,设置为 0,例如:,i+;,等价于,i+(0);,4.1.5,重载,+,和,-,例如:,用成员函数重载,class X,public:,operator +();,/,前缀方式,operator +(,int,);,/,后缀,方式,void f(X a),+a;,/a.operator+(),a+;,/a.operator+(0),a.operator+();,/,显式调用,意为+,a;,a.operator+(0);,/,显式调用,意为,a+;,4.1.5,重载,+,和,-,例如:,用友员函数重载,class Y,public:,friend,operator +(Y,/+a;,friend,operator +(Y&,int,);,/a+0;,void g(Y a),+a;,/operator+(a),a+;,/operator+(a,0),operator+(a);,/,显式调用,意为+,a;,operator+(a,0);,/,显式调用,意为,a+;,4.1.5,重载,+,和,-,重载,运算符+(或-)后,可以用两种方式使用:,a+;,/,隐式,调用,a.operator+(0);,/,显式调用,讨论,有时,它们的使用方式不等价:,a+3;,/error,但,operator+(a,3);,/ok,或,a.operator+(3);,/ok,合法,等价于,a+=3;,/,ex4,#,include,class Increase,public:,Increase()value=0;void display()const coutvaluen;,Increase operator+();Increase operator+(int);,private:unsigned value;,;,Increase Increase:operator+()value+;return*this;,/前缀,Increase Increase:operator+(int),/后缀,Increase temp;temp.value=value+;return temp;,void main(),Increase a,b,n;,for(int i=0;i 10;i+)a=n+;,cout“n=”;n.display();cout“a=”;a.display();,for(i=0;i 10;i+)b=+n;,cout “n=”;n.display();cout “b=”;b.display();,成员函数重载+,输出,n=10,a=9,n=20,b=20,/,ex5,#,include,class Increase,public:,Increase()value=0;void display()const coutvaluen;,friend,Increase operator +(Increase,friend,Increase operator +(Increase,private:unsigned value;,;,Increase operator+(Increase ,/前缀,Increase operator+(Increase&a,int),/后缀,Increase temp(a);a.value+;return temp;,void main(),Increase a,b,n;,for(int i=0;i 10;i+)a=n+;,cout“n=”;n.display();cout“a=”;a.display();,for(i=0;i 10;i+)b=+n;,cout“n=”;n.display();cout“b=”;b.display();,友员函数重载+,输出,n=10,a=9,n=20,b=20,4.1.6,重载赋值运算符,1.重载格式,X&X:operator=(,const,X&from),/,复制,X,的成员,返回类类型的引用是为了与,C+,原有赋值号的语义相匹配,用,const,修饰参数,保证函数体内不修改实际参数,/,ex6,class three_d,int,x,y,z;/3_d coordinates,public:,three_d,three_d operator+();void show();,void assign(,int mx,int,my,int mz,);,;,three_d&three_d:operator=(three_d&t,),x=t.x;y=t.y;z=t.z;return*this;,/,其它成员函数定义,main(),three_d a,b;,a.assign(1,2,3);b.assign(10,10,10);,(b=a)+;,a.show();b.show();,输出,1,2,3,2,3,4,能够正确使用赋值号语义,赋值表达式左边的表达式(对象)是左值,/,ex7,class three_d,int,x,y,z;/3_d coordinates,public:,three_d operator+();void show();,void assign(,int mx,int,my,int mz,);,;,x=t.x;y=t.y;z=t.z;return*this;,/,其它成员函数定义,main(),three_d a,b;,a.assign(1,2,3);b.assign(10,10,10);,a.show();b.show();,输出,1,2,3,1,2,3,b=a,返回是对象值而不是引用,+重载函数是传值参数,不能修改实参,b,three_d operator=(three_d t);,three_d three_d:operator=(three_d t),(b=a)+;,4.1.6,重载赋值运算符,2.有关说明,重载的运算符函数,operator=,不能被继承,重载的运算符函数,operator=,必须是成员函数,如果用户没有为类重载赋值运算符函数,编辑程序将生成一个,缺省的赋值运算符。,拷贝函数用于创建一个新对象,赋值运算符是改变一个已存在,的对象的值,4.1.7,重载,(),和,1.重载函数调用运算符,(),函数调用的一般格式为,(,),可以看成一个二元运算符,“,(),”,:,左操作数 为,右操作数 为,对应的函数是,operator(),设,x,是类,X,的一个对象,则表达式,x(arg1,arg2),可被解释为,x.operator()(arg1,arg2),只能用成员函数重载,不能用友员函数重载,/,ex8,用重载函数调用运算符实现数学函数的抽象,#,include,class F,public:double,operator(),(double x,double y),;,;,double F:operator()(double x,double y),return x*y+5;,main(),F,f,;,cout,f,(,5.2,2.5,),endl,;,C+,解释为,f.operator()(5.2,2.5),调用重载成员函数,double,operator(),(double x,double y),;,1.重载函数调用运算符,(),/,ex9,对比用普通成员函数的实现,#,include,class F,public:,double ff(double x,double y);,;,double F:ff(double x,double y),return x*y+5;,main(),F,fobj,;,cout,fobj,.ff(5.2,2.5),endl,;,注意,成员函数的定义和调用,1.重载函数调用运算符,(),4.1.7,重载,(),和,2.重载下标运算符,下标运算的格式为,可以看成一个二元运算符,“,”,:,左操作数 为,右操作数 为,对应的函数是,operator ,设,x,是类,X,的一个对象,则表达式,x y,可被解释为,x.operator (y),重载时,只能显式地声明一个参数,/,ex10,#include,class vector,public:,vector(,int,size);vector();,int,&operator (,int,i);,private:,int,*v;,;,vector:vector(,int,size)v=new,int,size ;,vector:vector()delete v;,int,&vector:operator (,int,i)return v i ;,main(),vector a(5);,a 2,=12;,cout,a 2,;,2.重载下标运算符,C+,解释为,a.operator()(2),调用重载成员函数,int,&operator (,int,i);,C+,解释为,a.operator()(2),调用重载成员函数,int,&operator (,int,i);,/,ex10,#include,class vector,public:,vector(,int,size);vector();,int,&operator (,int,i);,private:,int,*v;,;,vector:vector(,int,size)v=new,int,size ;,vector:vector()delete v;,int,&vector:operator (,int,i)return v i ;,main(),vector a(5);,a 2,=12;,cout,a 2,;,2.重载下标运算符,请试一试,不用重载下标算符函数,如何访问对象数据成员的元素?,
展开阅读全文