类的声明、定义、初始化

一、类的声明

1.不完全类

只声明而尚未定义的类称为不完全类
不完全类只能用于定义指针、引用、参数类型、返回值类型,不能定义对象
[cpp]  view plain  copy
  1. class Mat; //求定义的类  
  2. Mat Test(Mat& B);//正确  
  3. Mat *pMat;//正确  
  4. Mat mt;//错误,如果在任何位置(即使是在这句话的后面)定义了这个类,这句就是正确的  

二、类的定义

1.常用关键字

(1)typedef:

类可以定义自己的局部类型的名字,局部类型名和原类型名可以混用
定义方法:typedef 原类型名 局部类型名
例:
[cpp]  view plain  copy
  1. class Mat  
  2. {  
  3. public:  
  4.     typedef int myType  
  5.     myType s[MAX][MAX];  
  6.     Mat(myType a = MAX, myType b = MAX, myType type = 0);  
  7. };  
  8. Mat::Mat(int a, int b, int type)  
  9.     :sizei(a),sizej(b){  
  10.         memset(s, 0, sizeof(s));  
  11. }  

(2)const:

const成员函数返回的引用,也是const
[cpp]  view plain  copy
  1. /*从const成员函数返回的引用也是const*/  
  2. #include<iostream>  
  3. using namespace std;  
  4. class A  
  5. {  
  6. public:  
  7.     int x;  
  8.     void set(int x){this->x = x;}  
  9.     /*const成员函数返回的引用也是const,a 
  10.     如果把A&前面的const去掉会出错。 
  11.     因为返回的是一个const的对象,返回类型却不是const 
  12.     返回的内容和返回的类型不符*/  
  13.     const A& Test1()const  
  14.     {  
  15.         /*错误。这是const成员函数的特点*/  
  16.         x = 2;  
  17.         /*不限于*this。不管返回的是什么,哪怕是一个定义为非const的对象,结果也是一样的*/  
  18.         return *this;  
  19.     }  
  20. };  
  21. int main()  
  22. {  
  23.     A a, b;  
  24.     /*正确,虽然返回的是一个const,却用另一个非const来接收*/  
  25.     b = a.Test1();  
  26.     /*错误,既然是别名,那么别名的类型要与原来的类型相同*/  
  27.     A &c = a.Test1();  
  28.     //正确虽然在a.Test1()中a不能改变,但是这里已经出了这个成员函数的作用域  
  29.     a.set(2);  
  30.     //正确,b接收了a.Test1()返回的数据的内容,但是它不是const  
  31.     b.set(2);  
  32.     /*错误。a.Test1()是一个对象,这个对象是它的返回值, 
  33.     虽然没有名字,但是它就是a.Test1()的返回值, 
  34.     值是a.Test1()返回的值,类型是a.Test1()返回的类型, 
  35.     因此它是const*/  
  36.     a.Test1().set(2);  
  37.     return 0;  
  38. }  

(3)mutable:

mutable将数据声明为可变数据成员。可变数据成员永远不能成为const,即使它是const对象的成员
例:
[cpp]  view plain  copy
  1. class A  
  2. {  
  3. public:  
  4.     int x;  
  5.     mutable int y;  
  6.     A(int a, int b):x(a),y(b){}  
  7. };  
  8. int main()  
  9. {  
  10.     const A a(1,2);//const对象必须初始化  
  11.     a.x = 3;//错误  
  12.     a.y = 3;//正确  
  13.     return 0;  
  14. }  

(4)friend:

(5)static:


2.类外定义的特殊要求

如果成员函数在类外定义,则:
(1)成员名必须有 类名:: 来限定
(2)形参表和成员函数可以不限定
(3)函数返回类型,如果使用的是类定义的类型,则需要使用完全限定名
例:
[cpp]  view plain  copy
  1. class A  
  2. {  
  3. public:  
  4.     typedef int myType;  
  5.     int x;  
  6.     myType y;  
  7.     int Test1(int a);  
  8.     myType Test2(myType a);  
  9. };  
  10. int A::Test1(int a)  
  11. {  
  12.     x = a;  
  13.     return x;  
  14. }  
  15. A::myType A::Test2(myType a)  
  16. {  
  17.     y = a;  
  18.     return y;  
  19. }  

三、类的初始化

1.使用构造函数初始化

(1)在初始化列表中初始化与在构造函数的函数体中赋初值的区别

定义是指开辟空间,初始化是指给一个初值。
在初始化列表中初始化时,定义和初始化同时进行,因此初始化的顺序与初始化列表的顺序无关,只与声明成员的次序相同
在函数体上赋值时,已经定义好了,再赋值
例:
[cpp]  view plain  copy
  1. class A  
  2. {  
  3.     int x;  
  4. public:  
  5.     A(int i){x = i;cout<<"construct A "<<i<<endl;}  
  6.     ~A(){cout<<"delete A "<<x<<endl;}  
  7. };  
  8. class B  
  9. {  
  10.     A a;  
  11.     A b;  
  12.     A c;  
  13. public:  
  14.     B():c(3),b(2),a(1){cout<<"construct B"<<endl;}  
  15.     ~B(){cout<<"delete B"<<endl;}  
  16. };  
  17. int main()  
  18. {  
  19.     B b;  
  20.     return 0;  
  21. }  
输出结果:
construct A 1
construct A 2
construct A 3
construct B
delete B
delete A 3
delete A 2
delete A 1
这里特意让初始化列表的顺序不同,可以看出构造与析构的顺序与初始化列表无关,只与声明顺序有关

(2)必须使用初始化列表的成员

有些成员必须构造函数初始化列表中初始化,不可以在构造函数的函数体中初始化,如const成员或引用类型的成员
例:
[cpp]  view plain  copy
  1. class A  
  2. {  
  3.     int x;  
  4. public:  
  5.     A(int i):x(i){}  
  6. };  
  7. class B  
  8. {  
  9. public:  
  10.     int a;  
  11.     const int b;  
  12.     int &c;  
  13.     A d;  
  14.     //赋值  
  15.     B(int i)  
  16.     {  
  17.         a = i;//正确  
  18.         b = i;//错误,const不能被赋值  
  19.         c = i;//错误,引用不能被赋值  
  20.         d = i;//错误,已经开辟了空间,不能调用带一个参数的构造函数,也没有其它相应的函数  
  21.     }  
  22.     //初始化,这种做法效率较高,d(i)调用带一个参数的构造函数  
  23.     A(int i):a(i),b(i),c(i),d(i){}  
  24. };  

2.使用与初始化数组元素相同的方法初始化

对于没有定义构造函数并且全体数据成员均为public的类,可以采用与初始化数组元素相同的方式初始化成员,但这种方法不提倡
例:
[cpp]  view plain  copy
  1. class A  
  2. {  
  3. public:  
  4.     int a;  
  5.     char *b;  
  6. };  
  7. int main()  
  8. {  
  9.     A a = {1, "a+b"};  
  10.     return 0;  
  11. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值