1、C+更多特性卢佩新目录l l友元l l静态成员l l成员函数的重载拷拷贝贝构造函数构造函数运算符运算符类类型型转换转换操作符操作符重重载载newnew与与deletedelete流操作符流操作符Static Membersl l什么是静态成员staticstatic修修饰饰符符l l静态成员的特点静态数据成员l l所有的同一类对象都使用一份数据l l静态数据成员又称为类变量它属于它属于这这个个类类,被,被该类该类的全体的全体对对象共享象共享l l类变量的初始化class Counter class Counter static int cnt;static int cnt;类变量必须在clas
2、sclass声明的外声明的外面单独声明面单独声明,并初始化。如果不初始化,则编译器自动初始化0int Counter:cnt;或int Counter:cnt=0;静态函数成员l l公共的静态函数成员就是一个全局函数l l对公共的静态函数可以直接调用,不需要通过任何对象l l静态成员函数中不得使用非静态数据成员静态成员的应用例子 statics.cpp#include#include using namespace std;using namespace std;class Catclass Cat public:public:Cat(int age):itsAge(age)HowManyCa
3、ts+;Cat(int age):itsAge(age)HowManyCats+;virtual Cat()HowManyCats-;virtual Cat()HowManyCats-;virtual int GetAge()return itsAge;virtual int GetAge()return itsAge;virtual void SetAge(int age)itsAge=age;virtual void SetAge(int age)itsAge=age;static int HowManyCats;static int HowManyCats;private:private
4、:int itsAge;int itsAge;int Cat:HowManyCats=0;int Cat:HowManyCats=0;void TelepathicFunction();void TelepathicFunction();静态成员的应用例子 statics.cppint main()int main()const int MaxCats=5;int i;const int MaxCats=5;int i;Cat*CatHouseMaxCats;Cat*CatHouseMaxCats;for(i=0;iMaxCats;i+)for(i=0;iMaxCats;i+)CatHouse
5、i=new Cat(i);CatHousei=new Cat(i);TelepathicFunction();TelepathicFunction();for(i=0;iMaxCats;i+)for(i=0;iMaxCats;i+)delete CatHousei;delete CatHousei;TelepathicFunction();TelepathicFunction();return 0;return 0;void TelepathicFunction()void TelepathicFunction()cout There are;cout There are;cout Cat:H
6、owManyCats cats alive!n;cout Cat:HowManyCats cats alive!n;友元l l为什么需要友元:Friend As Bridges.l l什么东西可以成为友元友元函数友元函数 友元函数是可以直接友元函数是可以直接访问类访问类的私有成的私有成员员的非成的非成员员函数函数 它是定它是定义义在在类类外的普通函数,它不属于任何外的普通函数,它不属于任何类类,但需要在但需要在类类的定的定义义中加以声明,声明中加以声明,声明时时只需在只需在友元的名称前加上关友元的名称前加上关键键字字friendfriend友元友元类类 友元友元类类的所有成的所有成员员函数都是
7、另一个函数都是另一个类类的友元函的友元函数,都可以数,都可以访问访问另一个另一个类类中的中的隐隐藏信息(包括藏信息(包括私有成私有成员员和保和保护护成成员员)当希望一个当希望一个类类可以存取另一个可以存取另一个类类的私有成的私有成员时员时,可以将可以将该类该类声明声明为为另一另一类类的友元的友元类类友元的声明l l友元函数的声明友元函数的声明class Student class Student friend void Register(Student&);friend void Register(Student&);l l友元友元类类的声明的声明class Teacher;class Tea
8、cher;class Student class Student friend class Teacher;friend class Teacher;友元的例子 friend.cpp#include#include using namespace std;using namespace std;class beta;class beta;class alphaclass alpha private:private:int data;int data;public:public:alpha():data(3)alpha():data(3)friend int frifunc(alpha,beta
9、);friend int frifunc(alpha,beta);class betaclass beta private:private:int data;int data;public:public:beta():data(7)beta():data(7)friend int frifunc(alpha,beta);friend int frifunc(alpha,beta);友元的例子 friend.cppint frifunc(alpha a,beta b)int frifunc(alpha a,beta b)return(a.data+b.data);return(a.data+b.
10、data);int main()int main()alpha aa;alpha aa;beta bb;beta bb;cout frifunc(aa,bb)endl;cout frifunc(aa,bb)endl;return 0;return 0;成员函数的重载l l构造函数的重载缺省构造函数缺省构造函数自定自定义义构造函数构造函数拷拷贝贝构造函数构造函数构造函数的重载#include#include using namespace std;using namespace std;class Rectangleclass Rectangle public:public:Rectangle(
11、);Rectangle();Rectangle(int width,int length);Rectangle(int width,int length);Rectangle()Rectangle()int GetWidth()const return itsWidth;int GetWidth()const return itsWidth;int GetLength()const return itsLength;int GetLength()const return itsLength;private:private:int itsWidth;int itsWidth;int itsLen
12、gth;int itsLength;Rectangle:Rectangle()Rectangle:Rectangle()itsWidth=5;itsWidth=5;itsLength=10;itsLength=10;构造函数的重载Rectangle:Rectangle(int width,int length)Rectangle:Rectangle(int width,int length)itsWidth=width;itsWidth=width;itsLength=length;itsLength=length;int main()int main()Rectangle Rect1;Rec
13、tangle Rect1;cout Rect1 width:Rect1.GetWidth()endl;cout Rect1 width:Rect1.GetWidth()endl;cout Rect1 length:Rect1.GetLength()endl;cout Rect1 length:Rect1.GetLength()endl;int aWidth,aLength;int aWidth,aLength;cout Enter a width:;cout aWidth;cin aWidth;cout nEnter a length:;cout aLength;cin aLength;Rec
14、tangle Rect2(aWidth,aLength);Rectangle Rect2(aWidth,aLength);cout nRect2 width:Rect2.GetWidth()endl;cout nRect2 width:Rect2.GetWidth()endl;cout Rect2 length:Rect2.GetLength()endl;cout Rect2 length:Rect2.GetLength()endl;return 0;return 0;Copy Constructorl l当由一个已有的当由一个已有的对对象来构造一个新的象来构造一个新的对对象象时时,需,需要要
15、copy constructorcopy constructor默认的对象拷贝l l普通普通类类的的copy constructorcopy constructorC+编译器会自动给每一个类加上一个如果没有使用任何动态空间,则可以使用系统的:浅拷浅拷贝贝 (memcpy()will be called)(memcpy()will be called)如果该类使用了任何动态分配的内存,则需要重载copy constructor 深拷深拷贝贝 (need overload copy constructor)(need overload copy constructor)调用copy constru
16、ctorl l类类A A的定的定义义如下如下class A class A int a;int a;public:public:A(int v=0):a(v)A(int v=0):a(v);l l下面分下面分别别生成生成对对象象o1o1与与o2o2有何不同有何不同A o1(3);A o1(3);A o2=o1;A o2=o1;A o1(3);A o1(3);A o2;A o2;o2=o1;o2=o1;A o2=o1;使用copy constructorA o2;o2=o1;使用赋值语句拷贝构造函数的定义class A class A int a;int a;public:public:A(co
17、nst A&);A(const A&);A:A(const A&o)A:A(const A&o)a=o.a;a=o.a;拷贝构造函数的例子class V class V int*pv;int*pv;public:public:V(int a)pv=new int;*pv=a;V(int a)pv=new int;*pv=a;V()delete pv;V()delete pv;void disp()void disp()cout This=this cout This=this endl;endl;cout pv=pv cout pv=pv endl;endl;cout *pv=*pv cout
18、 *pv=*pv endl;endl;V a(3);V a(3);V b(5);V b(5);a.disp();a.disp();b.disp();b.disp();V a(3);V a(3);V b=a;V b=a;.*b.pv=100;*b.pv=100;a.disp();a.disp();b.disp();b.disp();V(const V&s)V(const V&s)pv=new int;pv=new int;*pv=*s.pv;*pv=*s.pv;自动调用构造函数l l问题问题出出现现Class AClass Aint a;int a;A oa=3;A oa=3;l l解决解决办办
19、法法class A class A int aint apublic:public:A(int i):a(i);A(int i):a(i);int main()int main()A oa=3A oa=3;自动调用的局限l l只会使用只含一个参数的constructorl l任何时候遇到歧义,则放弃尝试运算符的重载l l重载赋值运算符l l重载运算符的方法运算符作运算符作为为友元来重新定友元来重新定义义作作为为成成员员函数来重函数来重载载l l运算符操作的返回值值返回返回引用返回引用返回l l重载转换运算符Operator=l l赋值操作符的功能l l缺省的operator=缺省的operat
20、or=的问题class V class V int*pv;int*pv;public:public:V(int a)pv=new int;*pv=V(int a)pv=new int;*pv=aaV()delete pv;V()delete pv;void disp()void disp()cout This=this cout This=this endl;endl;cout pv=pv cout pv=pv endl;endl;cout *pv=*pv cout *pv=*pv endl;endl;V a(3);V a(3);V b(5);V b(5);a.disp();a.disp();
21、b.disp();b.disp();V a(3);V a(3);V b(5);V b(5);b=a;b=a;a.disp();a.disp();b.disp();b.disp();Operator=的重载l loperator=operator=作作为为成成员员函数重函数重载载class V class V V&operator=(const V&);V&operator=(const V&);V&V:operator=(const V&s)V&V:operator=(const V&s)*pv=*s.pv;*pv=*s.pv;return*this;return*this;Operator=
22、重载的注意事项l l可能的问题obj=obj;obj=obj;l l解决办法if(this=&s)if(this=&s)return*this;return*this;l l编译器会自动为一个类创建operator=Memberwise assignmentMemberwise assignment复复杂类杂类必必须须自己定自己定义义operator=operator=来来处处理堆内存的使理堆内存的使用用异端的operator=重载class Pixelclass Pixelint x,y;int x,y;int color;int color;public:public:Pixel(int
23、a=0,int b=0):x(a),y(b)Pixel(int a=0,int b=0):x(a),y(b)color=0;color=0;Pixel(int a,int b,int c)Pixel(int a,int b,int c)x=a;y=b;color=c;x=a;y=b;color=c;void draw()void draw()cout (x ,y cout (x ,y )=color endl;)=color endl;Pixel p1(1,2);Pixel p1(1,2);Pixel p2(3,5,1);Pixel p2(3,5,1);p1.draw();p1.draw();
24、p2.draw();p2.draw();Pixel p1(1,2);Pixel p1(1,2);Pixel p2(3,5,Pixel p2(3,5,1);1);p2=p1;p2=p1;p1.draw();p1.draw();p2.draw();p2.draw();Class Pixel Class Pixel Public:Public:Pixel&operator=(const Pixel&s)Pixel&operator=(const Pixel&s)x=s.y;y=s.x;color=x=s.y;y=s.x;color=!s.color;!s.color;copy constructor
25、与operator=l l什么什么时时候候调调用用copy constructorcopy constructorl l什么什么时时候候调调用用operator=operator=l l指出下面三种写法的差指出下面三种写法的差别别A oA o;A o;A o;o=A();o=A();A o1;A o1;A o2=o1;A o2=o1;A o;A o;直接调用直接调用constructorconstructor,构造对象,构造对象o oA o;A o;o=A();o=A();直接调用直接调用constructor constructor,构造对象,构造对象o o再构造出一个临时对象,并将该临再构
26、造出一个临时对象,并将该临时对象赋给时对象赋给o o,(operator=is(operator=is called)called)A o1;A o1;A o2=o1;A o2=o1;直接调用直接调用constructor constructor,构造对象,构造对象o1o1用用o1o1作参数,再调用作参数,再调用copy copy constructorconstructor构造对象构造对象o2o2单目运算符的重载1l loperator+operator+作作为为友元的重友元的重载载class A class A int a,b;int a,b;public:public:A(int x,i
27、nt y):a(x),b(y)A(int x,int y):a(x),b(y)friend A&operator+(A&);friend A&operator+(A&);A&operator+(A&x)A&operator+(A&x)x.a+;x.a+;x.b+;x.b+;return x;return x;单目运算符的重载2l loperator+operator+作作为为成成员员函函数的重数的重载载class A class A int a,b;int a,b;public:public:A(int x,int A(int x,int y):a(x),b(y)y):a(x),b(y)A&o
28、perator A&operator+();/+();/前前+;A&A:operator+()A&A:operator+()a+;b+;a+;b+;return return*this;*this;class A class A int a,b;int a,b;public:public:A(int x,int y):a(x),A(int x,int y):a(x),b(y)b(y)A&operator+();A&operator+();A operator+(int);/A operator+(int);/后后+;A A:operator+(int dummy)A A:operator+(i
29、nt dummy)A temp=*this;A temp=*this;a+;b+;a+;b+;return temp;return temp;单加与单减的麻烦l lPrefix与postfix?+a .vs.a+a .vs.a+l lC+的处理前加前加为为operator+(a)operator+(a)后加后加为为operator+(a,int)operator+(a,int)使用一个使用一个intint的的哑哑元元l l前+为左值,应该返回一个引用l l后+为右值,可以返回一个临时对象的值双目运算符的重载1l loperator+operator+作作为为友元的重友元的重载载class A
30、class A int a,b;int a,b;public:public:A(int x,int y):a(x),b(y)A(int x,int y):a(x),b(y)friend A operator+(const A&,const A&);friend A operator+(const A&,const A&);A operator+(const A&x,const A&y)A operator+(const A&x,const A&y)int a=x.a+y.a;int a=x.a+y.a;int b=x.b+y.b;int b=x.b+y.b;return A(a,b);retu
31、rn A(a,b);双目运算符的重载2l loperator+operator+作作为为成成员员函数的重函数的重载载class A class A int a,b;int a,b;public:public:A(int x,int y):a(x),b(y)A(int x,int y):a(x),b(y)A operator+(const A&);A operator+(const A&);A A:operator+(const A&x)A A:operator+(const A&x)return A(a+x.a,b+x.b);return A(a+x.a,b+x.b);转换运算符l l用于将一
32、个用于将一个对对象象转换转换成其他数据成其他数据类类型型operator operator 类类型名型名();();l l转换转换运算符没有返回运算符没有返回类类型型类类型名即返回型名即返回类类型型l l转换转换运算符的声明与定运算符的声明与定义义class RMB class RMB int y;int y;int j;int j;int f;int f;public:public:operator double()operator double()return y+j/10.0+f/100.0;return y+j/10.0+f/100.0;流操作符的重载l l作为友元函数的重载class
33、 A class A int a,b;int a,b;friend ostream&operator (ostream&,const friend ostream&operator (ostream&,const A&);A&);;ostream&operator (ostream&oo,const ostream&operator (ostream&oo,const A&x)A&x)oo (x.a ,x.b );oo (x.a ,x.b 的重载l l作作为为友元函数的重友元函数的重载载class A class A int a,b;int a,b;friend istream&operato
34、r (istream&,A&);friend istream&operator (istream&,A&);;istream&operator (istream&ii,A&x)istream&operator (istream&ii,A&x)char ch;char ch;ii ch;ii ch;ii x.a;ii x.a;ii ch;ii ch;ii x.b;ii x.b;ii ch;ii ch;return ii;return ii;可以重载哪些东西?l l编译器为类自动生成的元素 Default constructorDefault constructor Default destruc
35、torDefault destructor Default copy constructorDefault copy constructor Default operator=Default operator=l l所有的运算符不能重不能重载载的运算符:的运算符:,*,:,?:?:,sizeof,sizeof,#,#无法自己定无法自己定义义新的运算符新的运算符重载的要点l lOperator=只能当成员函数重载只能是成只能是成员员函数函数:=,()(),-,-*-*,类类型型转换转换函数函数l l推荐的原则所有一元运算符按成所有一元运算符按成员员函数来重函数来重载载l l建议以成员函数重载+=
36、+=,-=-=,/=/=,*=,=,&=&=,|=|=,%=%=,=,=l l其他二元运算符建议按友元重载rmb.h 程序#include#include#include#include#include#include using namespace std;using namespace std;class RMBclass RMBprivate:private:int y,j,f;int y,j,f;public:public:RMB(int,int,int);RMB(int,int,int);RMB(float);RMB(float);RMB(double);RMB(double);RM
37、B(const RMB&);RMB(const RMB&);RMB operator+(const RMB&);RMB operator+(const RMB&);RMB operator-(const RMB&);RMB operator-(const RMB&);RMB operator*(const int);RMB operator*(const int);RMB&operator=(const RMB&);RMB&operator=(const RMB&);operator float();operator float();operator long();operator long(
38、);friend ostream&operator(ostream&,const friend ostream&operator(istream&,RMB&);friend istream&operator(istream&,RMB&);rmb.cpp 程序#include rmb.h#include rmb.hRMB:RMB(int yuan,int jiao,int fen)RMB:RMB(int yuan,int jiao,int fen)y=yuan;y=yuan;j=jiao;j=jiao;if(jiao=10)if(jiao=10)y+;y+;j-=10;j-=10;f=fen;f
39、=fen;if(fen=10)if(fen=10)j+;j+;fen-=10;fen-=10;RMB:RMB(float a)RMB:RMB(float a)y=(int)a;y=(int)a;j=(int)(a-y)*10);j=(int)(a-y)*10);f=(int)(100*a)-(100*y)-(10*j);f=(int)(100*a)-(100*y)-(10*j);rmb.cpp 程序RMB:RMB(double a)RMB:RMB(double a)y=(int)a;y=(int)a;j=(int)(a-y)*10);j=(int)(a-y)*10);f=(int)(100*a
40、-100*y-10*j);f=(int)(100*a-100*y-10*j);RMB:RMB(const RMB&r)RMB:RMB(const RMB&r)y=r.y;j=r.j;f=r.f;y=r.y;j=r.j;f=r.f;RMB RMB:operator+(const RMB&r)RMB RMB:operator+(const RMB&r)int x=y+r.y;int x=y+r.y;int y=j+r.j;int y=j+r.j;int z=f+r.f;int z=f+r.f;if(z=10)if(z=10)y+;y+;z-=10;z-=10;return RMB(x,y,z);r
41、eturn RMB(x,y,z);rmb.cpp 程序RMB RMB:operator-(const RMB&r)RMB RMB:operator-(const RMB&r)return RMB(y-r.y,j-r.j,f-r.f);return RMB(y-r.y,j-r.j,f-r.f);RMB RMB:operator*(const int n)RMB RMB:operator*(const int n)float x=(float)*this;float x=(float)*this;cout x=x endl;cout x=x endl;x*=n;x*=n;cout x=x endl
42、;cout x=x endl;RMB t(x);RMB t(x);cout t=t endl;cout t=t endl;return t;return t;RMB&RMB:operator=(const RMB&r)RMB&RMB:operator=(const RMB&r)if(this=&r)if(this=&r)return*this;return*this;y=r.y;y=r.y;j=r.j;j=r.j;rmb.cpp 程序 f=r.f;f=r.f;return*this;return*this;RMB:operator float()RMB:operator float()retu
43、rn(float)(y+j/10.0+f/100.0);return(float)(y+j/10.0+f/100.0);RMB:operator long()RMB:operator long()return long(y*100+j*10+f);return long(y*100+j*10+f);ostream&operator(ostream&o,const RMB&r)ostream&operator(ostream&o,const RMB&r)o Y r.y .r.j r.f endl;o Y r.y .r.j r.f (istream&i,RMB&r)istream&operator
44、(istream&i,RMB&r)float f;float f;i f;i f;r=RMB(f);r=RMB(f);return i;return i;rmbmain.cpp 程序#include#include using namespace std;using namespace std;#include rmb.h#include rmb.hint main()int main()RMB r1(3.26f);RMB r1(3.26f);RMB r2(2.16f);RMB r2(2.16f);RMB r3=r1+r2;RMB r3=r1+r2;RMB r4=r2-r1;RMB r4=r2
45、-r1;RMB r5=r1*3;RMB r5=r1*3;cout r1=r1 endl;cout r1=r1 endl;cout r2=r2 endl;cout r2=r2 endl;cout r1+r2=r3 endl;cout r1+r2=r3 endl;cout r1-r2=r4 endl;cout r1-r2=r4 endl;cout r5=r5 endl;cout r5=r5 endl;练习一l l设计设计一个字符串一个字符串类类StringString,要求,要求该类该类能能够够完成以完成以下操作(用函数重下操作(用函数重载载完成)完成)要求:构造完整的类(构造、析构函数,拷贝构造
46、函数,重载操作符)并且实现以下功能 String1=String2+String3String1=String2+String3(重重载载)String1+=String2String1+=String2(重重载载)(int)String1(int)String1(重重载类载类型型转换转换int)int),将,将StringString对对象中的所有字符的象中的所有字符的ASCIIASCII相加后返回。相加后返回。String1 String1 String2String2(重重载载相等判断,两字符串相等返相等判断,两字符串相等返回真,不等返回假回真,不等返回假)cout String1cout String1cin String1(输输入符号重入符号重载载)l l编编写写测试测试程序程序测试该类测试该类