《单位竣工验收前提交质监存档文件资料(新版)》由会员分享,可在线阅读,更多相关《单位竣工验收前提交质监存档文件资料(新版)(44页珍藏版)》请在金锄头文库上搜索。
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 static int cntcnt; ;类变量必须在cla
2、ssclass声明的外声明的外面单独声明面单独声明,并初始化。如果不初始化,则编译器自动初始化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(intCat(int age):itsAge(ag
3、e)HowManyCatsage):itsAge(age)HowManyCats+; +; virtual Cat() virtual Cat() HowManyCatsHowManyCats-; -; virtual int virtual int GetAgeGetAge() return () return itsAgeitsAge; ; virtual void virtual void SetAge(intSetAge(int age) age) itsAgeitsAge = age; = age; static int static int HowManyCatsHowManyCa
4、ts; ; private:private:int int itsAgeitsAge; ;int Cat : int Cat : HowManyCatsHowManyCats = 0; = 0;void void TelepathicFunctionTelepathicFunction();();静态成员的应用例子 statics.cppint main()int main() const int const int MaxCatsMaxCats = 5; int i; = 5; int i;Cat *Cat *CatHouseMaxCatsCatHouseMaxCats;for (i = 0
5、; ifor (i = 0; iMaxCatsMaxCats; i+); i+) CatHouseiCatHousei = new Cat(i); = new Cat(i);TelepathicFunctionTelepathicFunction();(); for ( i = 0; ifor ( i = 0; iMaxCatsMaxCats; i+); i+) delete delete CatHouseiCatHousei;TelepathicFunctionTelepathicFunction();(); return 0;return 0; void void TelepathicFu
6、nctionTelepathicFunction()() coutcout There are ; There are ;coutcout Cat : Cat :HowManyCatsHowManyCats cats alive!n; cats alive!n; 友元l l为什么需要友元: Friend As Bridges.l l什么东西可以成为友元友元函数友元函数 友元函数是可以直接访问类的私有成员的非成友元函数是可以直接访问类的私有成员的非成员函数员函数 它是定义在类外的普通函数,它不属于任何类,它是定义在类外的普通函数,它不属于任何类,但需要在类的定义中加以声明,声明时只需在但需要在类
7、的定义中加以声明,声明时只需在友元的名称前加上关键字友元的名称前加上关键字friendfriend友元类友元类 友元类的所有成员函数都是另一个类的友元函友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的隐藏信息(包括数,都可以访问另一个类中的隐藏信息(包括私有成员和保护成员)私有成员和保护成员) 当希望一个类可以存取另一个类的私有成员时,当希望一个类可以存取另一个类的私有成员时,可以将该类声明为另一类的友元类可以将该类声明为另一类的友元类友元的声明l l友元函数的声明友元函数的声明class Student class Student friend void Register(
8、Student&);friend void Register(Student&);l l友元类的声明友元类的声明class Teacher;class Teacher;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;
9、 int data; public: public: alpha(): data(3) alpha(): data(3) friend int friend int frifuncfrifunc (alpha, beta); (alpha, beta);class betaclass beta private: private: int data; int data; public: public: beta () : data (7) beta () : data (7) friend int friend int frifunc(alphafrifunc(alpha, beta);, be
10、ta);友元的例子 friend.cppint int frifunc(alphafrifunc(alpha a, beta b) a, beta b) return (a.data + b.data); return (a.data + b.data); int main( )int main( ) alpha alpha aaaa; ; beta bb; beta bb; coutcout frifunc(aafrifunc(aa, bb) , bb) endlendl; ; return 0; return 0; 成员函数的重载l l构造函数的重载缺省构造函数缺省构造函数自定义构造函数自
11、定义构造函数拷贝构造函数拷贝构造函数构造函数的重载#include #include using namespace std;using namespace std;class Rectangleclass Rectangle public:public:Rectangle();Rectangle();Rectangle(intRectangle(int width, int length); width, int length);Rectangle() Rectangle() int int GetWidthGetWidth() const return () const return it
12、sWidthitsWidth; ; int int GetLengthGetLength() const return () const return itsLengthitsLength; ; private:private:int int itsWidthitsWidth; ;int int itsLengthitsLength; ;Rectangle:Rectangle()Rectangle:Rectangle() itsWidthitsWidth = 5; = 5;itsLengthitsLength = 10; = 10; 构造函数的重载Rectangle:Rectangle (in
13、t width, int length)Rectangle:Rectangle (int width, int length) itsWidthitsWidth = width; = width;itsLengthitsLength = length; = length; int main()int main() Rectangle Rect1;Rectangle Rect1;coutcout Rect1 width: Rect1.GetWidth() Rect1 width: Rect1.GetWidth() endlendl; ;coutcout Rect1 length: Rect1.G
14、etLength() Rect1 length: Rect1.GetLength() endlendl; ;int int aWidthaWidth, , aLengthaLength; ;coutcout Enter a width: ; aWidthaWidth; ;coutcout aLengthaLength; ;Rectangle Rect2(aWidth, Rectangle Rect2(aWidth, aLengthaLength););coutcout nRect2 width: Rect2.GetWidth() nRect2 width: Rect2.GetWidth() e
15、ndlendl; ;coutcout Rect2 length: Rect2.GetLength() Rect2 length: Rect2.GetLength() endlendl; ;return 0;return 0; Copy Constructorl l当由一个已有的对象来构造一个新的对象时,需当由一个已有的对象来构造一个新的对象时,需要要copy constructorcopy constructor默认的对象拷贝l l普通类的普通类的copy constructorcopy constructorC+编译器会自动给每一个类加上一个如果没有使用任何动态空间,则可以使用系统的: 浅拷
16、贝浅拷贝 ( (memcpymemcpy() will be called)() will be called)如果该类使用了任何动态分配的内存,则需要重载copy constructor 深拷贝深拷贝 (need overload copy constructor)(need overload copy constructor)调用copy constructorl l类类A A的定义如下的定义如下class A class A int a;int a;public:public:A(intA(int v = 0) : a(v) v = 0) : a(v) ;l l下面分别生成对象下面分别生
17、成对象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(const 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 *i
18、nt *pvpv; ;public:public:V(intV(int a) a) pvpv = new int; * = new int; *pvpv = a; = a; V( ) delete V( ) delete pvpv;void void dispdisp( ) ( ) coutcout This= this This= this endlendl; ;coutcout pvpv= = pvpv endlendl; ;coutcout * *pvpv= *= *pvpv endlendl; ; ;V a(3);V a(3);V b(5);V b(5);a.dispa.disp();
19、();b.dispb.disp();();V a(3);V a(3);V b = a;V b = a;.* *b.pvb.pv=100;=100;a.dispa.disp( );( );b.dispb.disp( );( );V(const V& s) V(const V& s) pvpv = new int; = new int;* *pvpv = * = *s.pvs.pv; ; 自动调用构造函数l l问题出现问题出现Class AClass Aint a;int a;A A oaoa = 3; = 3;l l解决办法解决办法class A class A int aint apublic
20、:public:A(intA(int i) : a(i) ; i) : a(i) ;int main()int main() A A oaoa=3=3; ; 自动调用的局限l l只会使用只含一个参数的constructorl l任何时候遇到歧义,则放弃尝试运算符的重载l l重载赋值运算符l l重载运算符的方法运算符作为友元来重新定义运算符作为友元来重新定义作为成员函数来重载作为成员函数来重载l l运算符操作的返回值返回值返回引用返回引用返回l l重载转换运算符Operator=l l赋值操作符的功能l l缺省的operator=缺省的operator=的问题class V class V in
21、t *int *pvpv; ;public:public:V(intV(int a) a) pvpv = new int; * = new int; *pvpv = = aaV( ) delete V( ) delete pvpv;void void dispdisp( ) ( ) coutcout This= this This= this endlendl; ;coutcout pvpv= = pvpv endlendl; ;coutcout * *pvpv= *= *pvpv endlendl; ; ;V a(3);V a(3);V b(5);V b(5);a.dispa.disp();
22、();b.dispb.disp();();V a(3);V a(3);V b(5);V b(5);b = a;b = a;a.dispa.disp( );( );b.dispb.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) * *pvpv = * = *s.pvs.pv; ;return *t
23、his;return *this;Operator=重载的注意事项l l可能的问题objobj = = objobj; ;l l解决办法if (this = &s)if (this = &s)return *this;return *this;l l编译器会自动为一个类创建operator=MemberwiseMemberwise assignment assignment复杂类必须自己定义复杂类必须自己定义operator=operator=来处理堆内存的使来处理堆内存的使用用异端的operator=重载class Pixelclass Pixelint x, y;int x, y;int
24、color;int color;public:public:Pixel(intPixel(int a=0, int b=0):x(a),y(b) a=0, int b=0):x(a),y(b) color=0;color=0;Pixel(intPixel(int a, int b, int c) a, int b, int c) x = a; y = b; color = c;x = a; y = b; color = c; void draw( ) void draw( ) coutcout ( x , y ( x , y )= color )= color endlendl; ; ;Pix
25、el p1(1, 2);Pixel p1(1, 2);Pixel p2(3, 5, 1);Pixel p2(3, 5, 1);p1.draw( );p1.draw( );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
26、& 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与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
27、 = o1;A o;A o;直接调用直接调用constructorconstructor,构造对象构造对象o oA o;A o;o = A( );o = A( );直接调用直接调用constructorconstructor ,构造对象,构造对象o o再构造出一个临时对象,并将该临再构造出一个临时对象,并将该临时对象赋给时对象赋给o o, (operator= is (operator= is called)called)A o1;A o1;A o2 = o1;A o2 = o1;直接调用直接调用constructorconstructor ,构造对象,构造对象o1o1用用o1o1作参数,再调
28、用作参数,再调用copy copy constructorconstructor构造对象构造对象o2o2单目运算符的重载1l loperator +operator +作为友元的重载作为友元的重载class A class A int a,b;int a,b;public:public:A(intA(int x, int y) : a(x), b(y) 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 +;
29、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(intA(int x, int x, int y) : a(x), b(y) y) : a(x), b(y) A& operator A& operator + ( );/+ ( );/前前+;A& A:operator + ( )A& A:operator + ( ) a+; b+;a+; b+;return return *
30、this;*this; class A class A int a,b;int a,b;public:public:A(intA(int x, int y) : a(x), x, int y) : a(x), b(y) b(y) A& operator + ( );A& operator + ( );A operator+ (int );/A operator+ (int );/后后+;A A A:operator+(intA:operator+(int dummy) dummy) A temp = *this;A temp = *this;a+; b+;a+; b+;return temp;
31、return temp; 单加与单减的麻烦l lPrefix与postfix?+a .vs. a+a .vs. a+l lC+的处理前加为前加为operator+(a)operator+(a)后加为后加为operator+(a,intoperator+(a,int) ) 使用一个使用一个intint的哑元的哑元l l前+为左值,应该返回一个引用l l后+为右值,可以返回一个临时对象的值双目运算符的重载1l loperator +operator +作为友元的重载作为友元的重载class A class A int a,b;int a,b;public:public:A(intA(int x,
32、int y) : a(x), b(y) 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);return A(a,b);
33、 双目运算符的重载2l loperator +operator +作为成员函数的重载作为成员函数的重载class A class A int a,b;int a,b;public:public:A(intA(int x, int y) : a(x), b(y) 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.
34、b); 转换运算符l l用于将一个对象转换成其他数据类型用于将一个对象转换成其他数据类型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/
35、100.0; ;流操作符的重载l l作为友元函数的重载class A class A int a,b;int a,b;friend friend ostreamostream& operator (& operator (ostreamostream&, const &, const A&);A&); ;ostreamostream& operator (& operator (ostreamostream& & oooo, const , const A&x)A&x) oooo ( x.a , x.b ); ( x.a , x.b 的重载l l作为友元函数的重载作为友元函数的重载class
36、A class A int a,b;int a,b;friend friend istreamistream& operator (& operator (istreamistream&, A&);&, A&); ;istreamistream& operator (& operator (istreamistream& ii, A&x)& ii, A&x) char char chch; ;ii ii chch; ;ii x.a;ii x.a;ii ii chch; ;ii x.b;ii x.b;ii ii chch; ;return ii;return ii; 可以重载哪些东西?l l编译
37、器为类自动生成的元素 Default constructorDefault constructor Default destructorDefault destructor Default copy constructorDefault copy constructor Default operator=Default operator=l l所有的运算符不能重载的运算符:不能重载的运算符: ,* *,:,?:?:,sizeofsizeof, , # #,#无法自己定义新的运算符无法自己定义新的运算符重载的要点l lOperator=只能当成员函数重载只能是成员函数只能是成员函数: : = =
38、,( )( ), ,-,-*-*,类型转换函数,类型转换函数l l推荐的原则所有一元运算符按成员函数来重载所有一元运算符按成员函数来重载l l建议以成员函数重载+=+=,-=-=,/=/=,*=*=,=,&=&=,|=|=,%=%=,=,=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;p
39、ublic:public: RMB(intRMB(int, int, int);, int, int);RMB(float);RMB(float); RMB(double); RMB(double); RMB(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); R
40、MB& operator= (const RMB&); RMB& operator= (const RMB&); operator float(); operator float(); operator long(); operator long(); friend friend ostreamostream& operator (& operator (& operator (istreamistream&, RMB&);&, RMB&); ; ;rmb.cpp 程序#include #include rmb.hrmb.h RMB:RMB(intRMB:RMB(int yuanyuan, i
41、nt , int jiaojiao, int fen), int fen) y = y = yuanyuan; ;j = j = jiaojiao; ;if(jiaoif(jiao = 10) = 10) y+; y+; j -= 10; j -= 10; f = fen;f = fen; if(fen = 10) if(fen = 10) j+; j+; fen -= 10; fen -= 10; RMB:RMB(float a)RMB:RMB(float a) y = ( y = (int)aint)a; ; j = ( j = (int)(aint)(a - y) * 10); - y)
42、 * 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 - 100*y - 10*j); f = (int) (100*a - 100*y - 10*j); RMB:RMB(const RMB& r)RMB:RMB(
43、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,
44、z); return 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; coutcout
45、x= x x= x endlendl; ; x *= n; x *= n; coutcout x= x x= x endlendl; ; RMB t(x); RMB t(x); coutcout t= t t= t endlendl; ; 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;rm
46、b.cpp 程序 f = r.f; f = r.f; return *this; return *this; RMB:operator float()RMB:operator float() return (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); ostreamos
47、tream& operator (& operator (ostreamostream& o, const RMB& r)& o, const RMB& r) o Y r.y . r.j r.f o Y r.y . r.j r.f (& operator (istreamistream& i, RMB& r)& 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 nam
48、espace 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 - 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
49、; 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,要求该类能够完成以,要求该类能够完成以下操作(用函数重载完成)下操作(用函数重载完成)要求:构造完整的类(构造、析构函数,拷贝构造函数,重载操作符)并且实现以下功能 String1=String2+String3String1=String2+String3
50、( (重载重载) ) String1 += String2String1 += String2( (重载重载) ) (int)String1(int)String1( (重载类型转换重载类型转换int)int),将,将StringString对对象中的所有字符的象中的所有字符的ASCIIASCII相加后返回。相加后返回。 String1 String1 String2String2( (重载相等判断,两字符串相等返重载相等判断,两字符串相等返回真,不等返回假回真,不等返回假) ) coutcout String1 String1 String1( (输入符号重载输入符号重载) )l l编写测试程序测试该类编写测试程序测试该类