1、3.3 静态类成员3.3.1 静态数据成员 希望数据为类的所有对象共享,而不是每个类对象维持一个独立的数据成员。例如:计数在程序的任意一点一共创建了多少个此类类型的对象。静态数据成员对每个类类型只有一个拷贝,由该类对象共享访问。非静态数据成员对每个类对象都有自己的拷贝。可以实现信息隐藏,可以是private成员。3.3.1.1 类定义内声明在类体中数据成员声明前加上static关键字,使该数据成员成为静态的例如:class student int num;float score;public:static float passmark;static int passnum;student(in
2、t a,float f)num=a;score=f;3.3.1.2 类定义外初始化 语法:数据类型 类名:数据成员名=初值;注意:如果没有初值,系统自动初始化为0。整型const静态数据成员可以在类定义体内用常量值初始化,但仍要在类定义体外定义该数据成员且不能再指定初始值。静态数据成员的初始化不应该放在头文件中。一般放在类定义之后,main函数之前。产生类对象之前可能用到静态数据成员。例如:class Accout static const int namesize=16;static const char namenamesize;const int Accout:namesize;cons
3、t char Accout:namenamesize=”saving account”;3.3.1.3 静态数据成员的访问 类的成员函数中访问:用静态数据成员名直接访问 非成员函数中访问public静态数据成员:类名:静态数据成员名 对象.静态数据成员名 指向对象的指针-静态数据成员名 例如:计数已创建对象的数目 class Data int num;float score;public:static int object;Data(int a,float f):num(a),score(f)object+;Data()object-;3.3.2 静态成员函数 希望在产生对象之前访问priva
4、te静态数据成员 3.3.2.1 声明与定义 在类内普通成员函数声明前加上static关键字,在类外定义前不需再加static。注意:静态成员函数没有this指针,不能访问类的非静态成员,只能访问类的静态数据成员或是调用其它静态成员函数。3.3.2.2 调用 类名:静态函数名(参数表);对象.静态函数名(参数表);指向对象的指针-静态函数名(参数表);例如:class Small static int object;public:Small()object+;static int get_n()return object;Small()object-;int Small:object=0;in
5、t main()int n;n=Small:get_n();/3.3.3 全局、静态局部类对象 3.3.3.1 局部静态类对象 在函数或复合语句内,用static关键字定义的对象。例如:int fun()static Data(1,89.0);return 0;代码执行过程中第一次遇到该对象定义时,构造函数被调用,程序运行中仅调用一次;在程序运行结束前,调用析构函数,也只调用一次。例如:class demo public:demo()cout”object constructorn”;demo()cout”object destructor n”;void fun()static demo d
6、1;int main()coutmain startn;fun();coutagainn;fun();输出:main start coutmain endn;object constructor again main end object destructor 3.3.3.2 全局类对象 在函数外定义的对象。构造函数在main函数执行前被调用,析构函数在程序运行结束前调用。例如:class demo public:demo()coutobject constructor n;demo()coutobject destructor n;int main()coutmain startn;cout
7、main endn;return 0;输出:object constructor static demo d1;main start main end object destructor 3.4 友元3.4.1 友元函数3.4.1.1友元函数的声明 允许一个类授权其它的函数或类访问它的非公有成员。友元声明以friend关键字开头,只能出现在类的定义中。友元不是类的成员,不受访问说明符的影响。一般将类中所有友元关系的声明放在类头之后。语法:friend 数据类型 函数名(参数标);3.4.1.2 友元函数的参数 成员函数由对象调用,系统传递this指针使其可以访问对象的成员。友元函数没有this
8、指针,要访问对象的成员,必须将要访问的对象作为参数传递。访问类对象的成员必须加上对象名和成员访问运算符。例如:class Data friend void get_val(Data&it,int n,float s);int num;float score;public:Data(int a,float f)num=a;score=f;Data()num=0;score=0.0;void print();void Data:print()coutnum“n”score,或者任何赋值运算符重载函数必须声明为类的一个成员函数。赋值运算符重载用于“=”两侧的对象都已经存在时,一个类对象向该类的另一个
9、对象赋值。一般在对象的数据成员是指针时用来进行深层复制。例如:demo d1(1,4.2);/构造函数 demo d2=d1;/拷贝构造函数 d3=d2;/赋值 注意:确保没有将对象复制给它自身 重新使用被赋值对象中的资源或删除它 从源对象上复制内容到目的对象 例如:class Tstring char*str;int len;public:Tstring(const char*p);Tstring()delete str;Tstring(const Tstring&source);Tstring&operator=(Tstring&it);Tstring&Tstring:operator=(
10、Tstring&it)if(this=&it)return*this;delete str;len=it.len;str=new charlen strcpy(str,it.str);return*this;赋值运算符重载也可以用于为一个类对象赋以不是该类类型的值。例如希望实现如下赋值:Tstring car(“benz”);car=“bmw”;在类定义中增加成员函数:Tstring&operator=(const char*);Tstring&Tstring:operator=(const char*cst)if(cst=0)len=0;delete str;str=0;else len=s
11、trlen(cst)+1;delete str;str=new charlen strcpy(str,it.cst);return*this;4.4 下标运算符 的重载 可以重载用于检查数组的下标是否越界 定义:operator(int index)调用:对象下标 出现在赋值运算符左侧,应该返回左值(指针、引用),出现在赋值运算符右侧,应该返回元素的值,但是函数只有一种返回类型,只有返回引用可以作为左值。例如:class intarray int size;int*ip;public:intarray(unsigned maxsize)size=maxsize;ip=new intsize;i
12、ntarray()delete ip;int&operator(index);int&intarray:operator(index)if(index=size)cout”out of range!n”;exit(1);return ipindex;int main()int size=100;intarry a(size);for(int i=0;i的重载 赋予类类型类似指针的行为 定义:数据类型 operator-()调用:对象-成员,相当于:(对象operator-()-成员 注意:对-的重载必须返回指向类对象的指针 -后的成员必须是返回的指针可以访问的成员 在返回的指针上再应用-以访问
13、该成员。例如:class foo public:int m;class z public:foo f;foo*operator-()return&f;int main()z z1;z1-m=0;/可用于访问对象成员的成员 4.6 函数调用运算符()的重载 重载了()运算符的对象称为function object,可作为函数来使用 定义:数据类型 operator()(参数表)调用:类对象(参数表)例如:class lessthan int val;public:lessthan(int x)val=x;bool operator()(int value)const;bool lessthan:
14、operator()(int value)const return valueval;int main()lessthan it(10);int a=5;if(it(a)cout”less than”;return 0;例如:class absint public:int operator()(int value)int result=valuea;coutitabs(a);return 0;4.7 用户定义的转换 隐式调用4.7.1 构造函数作为转换函数 只有一个基本类型参数(可以还有其它缺省参数)的构造函数,可以作为类型转换构造函数,实现转换:基本类型类类型 使用构造函数执行隐式转换时,构
15、造函数参数类型不必与被转换值的类型完全一致,编译器会在调用构造函数执行用户定义的转换之前,对实参应用标准转换。例如:class demo friend demo operator+(demo&d1,demo&d2);int a;public:demo(int x=0)/intdemo a=x;int main()demo d1(3),d2;d2=5+d1;/5demo,相当于demo temp(5);d2=temp+d1;d2=d1+4.2;/4.2intdemo 类A的构造函数将类B的对象(或引用)作为它的单个参数,可以作为类型转换构造函数,实现转换:B类类型A类类型 例如:class B
16、public:B();class A public:A(B&b);void fun(A a)int main()B b1;fun(b1);/相当于A temp(b1);/fun(temp);调用构造函数A(b1)把b1转换成A类型的值。编译器调用构造函数创建一个A类型临时对象,将临时对象的值传递给fun()函数。4.7.2 类型转换运算符重载(转换函数)定义:operator 类型()实现类类型和转换函数中指定的类型之间的转换注意:转换函数不允许定义返回类型,但必须有返回值。只能定义成类的成员函数,转换函数中指定的类型可以是内置类型、类类型。例如:class demo demo operato
17、r+(demo&d1,demo&d2);int a;float b;public:demo(int x,float y)a=x;b=y;operator int()return a;int main()demo d1(4,7.5);int a=5+d1;/调用d1.operator int()将d1intdouble f=d1+3.9;/调用d1.operator int()将d1intdouble couta”n”f”n”;4.7.3 构造函数和转换函数的相互影响 转换函数执行后,可以用标准转换把转换函数的结果转换成目标类型;在构造函数执行转换之前,可以用标准转换把要转换的值转换成构造函数参数的类型。现类型目标类型转换序列:标准转换用户定义的转换标准转换 当不只一个转换序列可以被应用时,编译器必须选择最好的序列执行转换。标准转换成为选择的依据。若所有的转换都一样好,则出现二义性。例如:class demo int a;public:demo(int x=0)/intdemoa=x;operator int()return a;operator float()return a;int main()demo d1(3);long v=d1;/调用d1.operator int()将d1intlong /调用d1.operator float()将d1floatlong
侵权处理QQ:3464097650--上传资料QQ:3464097650
【声明】本站为“文档C2C交易模式”,即用户上传的文档直接卖给(下载)用户,本站只是网络空间服务平台,本站所有原创文档下载所得归上传人所有,如您发现上传作品侵犯了您的版权,请立刻联系我们并提供证据,我们将在3个工作日内予以改正。