《7.2类的特殊成员》由会员分享,可在线阅读,更多相关《7.2类的特殊成员(28页珍藏版)》请在金锄头文库上搜索。
1、7.2类的特殊成员7.2 类的特殊成员一、this指针在对象调用自己的非静态成员函数时,会自动传给成员函数一个指针参数“this”,这个指针指向该对象自己。该参数是隐含的不可见,在被调用的成员函数内,出现的所有本类成员前都隐含的加上“this-”,也可以显式使用this指针。例:class complexprivate:double real;double image;public:void set(double r,double i)this-real=r;this-image=i;void display()coutreal+imageiendl;void main()complex x,
2、y;x.set(1,3);x.display();y.set(3,5);y.display();注:“set”函数把this指针显式写出了,和原先效果一样。this指针使得对象能够访问自己的成员。二、静态成员类的静态成员属于类本身,而不属于具体的某个对象,所以一个类静态成员只有一个数据拷贝。类的静态数据成员是在类定义语句被执行时即创建,所以是静态生存期,与对象的创建和注销无关。定义方法:在类成员定义中加关键字“static”,然后在类外为静态数据成员分配内存空间并初始化。调用方法:内部,任何成员函数都可以直接调用;外部,用任何一个该类成员调用,或者用类名加“:”直接调用。例:class com
3、plexprivate:double real;double image;public:static int sum;void set(double r,double i)real=r;image=i;sum+; /用静态成员统计set函数的调用次数void display()coutreal+imageiendl;int complex:sum=0;void main()complex x,y;x.set(1,3);y.set(3,5);coutx.sum;coutcomplex:sum;注:也可以定义静态函数成员。静态成员函数的特点是,不会自动传递this指针,所以静态成员函数一般专用于处
4、理静态数据成员。三、友元在类中可以指定另一个类或别的函数为自己的友元。友元和类内部成员函数的访问权限相同,即友元可以访问类的所有成员。例:class complexfriend void set(double r,double i,complex *p); /声明了一个友元函数friend class c; /声明了类c是类complex的友元friend void b:f1(); /声明了类b的成员函数f1是友元函数private:double real;double image;public:void display()coutreal+imageireal=r;p-image=i;voi
5、d main()complex x;set(1,3,&x);x.display();注意:1. 友元函数并不是类的一个成员,而是单独的一个外部函数。友元函数要访问类的成员,需要利用对象指针等参数,指定要访问的是哪个对象的成员。2. 如果指定类b是类a的友元类,则类b中的所有成员函数都可以任意访问类a的成员。但是反过来类a并不是类b的友元,不能任意访问类b的成员。四、常量成员和对象成员类中的数据成员是常量或者另一个类的对象的情况。例:class Bint s;class AB x;const int y;注意:定义类的时候不能给常量成员指定初值,常量成员是属于对象的,每个对象的同名常量成员可以取
6、不同的值。五、构造函数1. 因为对象定义后在外部无法访问私有的成员,所以用一个特殊的成员函数,构造函数给对象初始化。当系统新定义一个对象时,会自动调用构造函数。构造函数名字与类名相同,没有返回值类型,可以重载,应设置为公有权限。如果没有定义任何构造函数,系统会自动产生一个默认构造函数,这个默认函数没有参数并且什么也不做。如果自定义了构造函数,系统就不会自动产生默认构造函数,注意这时不带参数定义对象可能就会出错。例:class complexprivate:double real;double image;public:complex(double r,double i) /构造函数real=r
7、;image=i;void set(double r,double i)real=r;image=i;void display()coutreal+imageiendl;void main()complex x(1,3),y(3,4); /通过构造函数初始化complex z; /错误,此时已经没有自动生成的无参构造函数了x.display();y.set(3,5);y.display();注:构造函数如果要求参数,定义对象时必须用括号加上初始化参数。构造函数不要求参数,定义时对象名后不加括号。构造函数的参数可以带上默认值。例:class complexprivate:double real;
8、double image;public:complex(double r=0,double i=0) /构造函数real=r;image=i;.;void main()complex x; /构造函数默认参数,复数为0complex y(3,4);2. 冒号初始化列表C+允许构造函数在冒号后加成员初始化列表,列表中用括号给出初始化参数。初始化列表中列出的数据成员初始化的顺序,按照类的声明中这些成员出现的顺序进行,不是按照初始化列表中出现的顺序。一般初始化列表中的顺序应和声明的顺序一致。类的对象成员,类的常量成员,类的引用型成员(相当于常量),对象继承,这些情况下都必须使用初始化列表。对于有构造
9、函数的数据成员,用初始化列表效率较高。例:class complexprivate:double real;double image;public:complex(double r=0,double i=0):real(r),image(i).;void main()complex x;complex y(3,4);例:class c1public:c1(int i=0):a(i)int a;class c2public:c2(int i=0):t(5),a(b+1),b(i)c1 t;const int b;int a;void main()c2 x,y(3);coutx.ay.a;注意:冒
10、号初始化列表中不能出现this指针,此时对象还没有创建好。构造函数的函数体中可以用this指针,指向刚创建的对象。冒号初始化列表中只能出现成员名,因此用初始化列表时,构造函数形参可以和成员重名。例:class A public: A(int x = 0) : x(x) x=2; int x;“x(x)”括号外的一定是数据成员x,括号里的按照作用范围小优先原则,是形参x。“x=2;”按照作用范围小优先原则,是形参x,数据成员x不变。3. 构造函数中开辟动态空间在类中有一个指针成员,这个指针用来挂载动态申请的存储空间。例:class personprivate:char *name;int age
11、;public:person(int a,char *p=noname);void display()coutname:name age:ageendl;person:person(int a,char *p):age(a)name=new charstrlen(p)+1;strcpy(name,p);void main()char t20;int a;person x(18,tom);coutt;couta;person y(a,t);x.display();y.display();六、析构函数析构函数用来在对象注销之前执行一些操作,特别是释放动态开辟的内存空间等操作。析构函数名字是类名前加
12、“”,没有返回值类型,一个类只有一个析构函数,不可以重载,没有参数,应设置为公有权限。例:class personprivate:char *name;int age;public:person(int a,char *p=noname):age(a)name=new charstrlen(p)+1;strcpy(name,p);person()delete name; void display()coutname:name age:ageendl;七、转换构造函数1. 如果构造函数可以只带一个参数,这个构造函数就是隐式定义的类型转换构造函数,可以把这个参数的数据类型转换为该类得类型。例:重载复数类的构造函数class complexprivate:double real;double image;public:void set(double r,double i)real=r;image=i;void display()coutreal+imageiendl;complex(double r,double i)real=r;image=i;complex(double x):real(x),image(x) /转换构造函数;