【C++初阶】类与对象(下)

王國慶  论坛元老 | 2025-3-9 13:45:24 | 来自手机 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 1045|帖子 1045|积分 3139

目录
再探构造函数:初始化列表
使用方法:
特点:
1、初始化列表是每个成员变量界说初始化的地方
2、每一成员变量在初始化列表只出现一次
3、必须在初始化列表中出初始化的成员变量
4、成员变量给缺省值
5、在构造函数体内初始化和在初始化列表中初始化有什么区别?
6、指针成员变量初始化
7、成员变量初始化次序
注:()和{}初始化使用
总结:
类型转换
static成员
静态成员的调用:
静态成员变量:
1、
2、
​编辑3、
静态成员函数:
1、
2、
3、
注:静态成员也受访问限定符的限制
代码:
友元
内部类
匿名对象
特点:
1、
2、
3、使用场景
4、
5、匿名对象和暂时对象的区别


再探构造函数:初始化列表

在前面构造函数的学习中,成员变量的初始化重要在函数体内赋值,但还有一种初始化的方法,就是:初始化列表
使用方法:

在函数名下,以一个冒号开头,接着是一个以逗号分隔的数据成员列表,每一个成员变量背面跟一个放在括号中的初始值或表达式
  1. class A
  2. {
  3. public:
  4.         A()
  5.          :_a1(0)//成员变量初始化
  6.          , _a2(0)
  7.         {
  8.                
  9.         }
  10. private:
  11.         int _a1;
  12.         int _a2;
  13. };
  14. int main()
  15. {
  16.     A a(1,1);//对象初始化
  17.     return 0;
  18. }
复制代码
特点:

1、初始化列表是每个成员变量界说初始化的地方

在语法上可以这么理解:初始化列表是每个成员变量界说初始化的地方
2、每一成员变量在初始化列表只出现一次

  1. class A
  2. {
  3. public:
  4.         A()
  5.                 :_a1(0)
  6.       //,_a1(1)//error
  7.                 , _a2(0)
  8.         {
  9.                
  10.         }
  11. private:
  12.         int _a1;
  13.         int _a2;
  14. };
复制代码

3、必须在初始化列表中出初始化的成员变量

   1、引用成员变量
  2、const成员变量
  3、没有默认构造函数的类类型成员变量
  

正确代码:
  1. class B
  2. {
  3. public:
  4.         B(int b)
  5.         {
  6.                 _b = b;
  7.         }
  8. private:
  9.         int _b;
  10. };
  11. class A
  12. {
  13. public:
  14.         A(int a1, int a2)
  15.                 :_a1(a1)
  16.                 , _a2(a2)
  17.                 , _a3(1)
  18.                 , _a4(1)
  19.                 , _a5(1)
  20.         {
  21.         }
  22. private:
  23.         int _a1;
  24.         int _a2;
  25.        
  26.         //必须在初始化列表上初始化的成员变量
  27.         const int _a3;
  28.         const int& _a4;
  29.         //没有默认构造的自定义类型成员变量也必须在初始化列表上初始化
  30.         B _a5;
  31. };
  32. int main()
  33. {
  34.         A a1(1, 1);
  35.         return 0;
  36. }
复制代码
4、成员变量给缺省值

可以在成员变量声明时给缺省值,这里的缺省值其实就是给初始化列表的,当成员变量给了缺省值时,初始化列表就按照缺省值初始化成员变量
  1. class B
  2. {
  3. public:
  4.         B(int b)
  5.         {
  6.                 _b = b;
  7.         }
  8. private:
  9.         int _b;
  10. };
  11. class A
  12. {
  13. public:
  14.         A(int a1, int a2)
  15.         {
  16.         }
  17. private:
  18.         int _a1 = 0;
  19.         int _a2 = 0;
  20.         const int _a3 = 1;
  21.         const int& _a4 = 1;
  22.     B _a5 = 1;
  23. };
  24. int main()
  25. {
  26.         A a1(1, 1);
  27.         return 0;
  28. }
复制代码
5、在构造函数体内初始化和在初始化列表中初始化有什么区别?

  1. //函数体内就相当于下面这种:
  2. int i;
  3. i = 1;
  4. //初始化列表中初始化就相当于:
  5. int i = 1;
复制代码
6、指针成员变量初始化

  1. class A
  2. {
  3. public:
  4.     A(int n)
  5.         :_a((int*)malloc(n))
  6.     {
  7.     }
  8. private:
  9.     int* _a;//指针成员变量
  10.   //int* _a = (int*)malloc(n);
  11. }
复制代码
7、成员变量初始化次序

初始化列表中按照成员变量在类中声明次序举行初始化,和在初始化列表中出现的次序无关
以是成员变量声明次序和初始化列表中次序要保持一致

注:()和{}初始化使用

  1. 注意事项:
  2. //int i(1);//error
  3. int i{ 1 };//可以用{}来初始化,不能用()
复制代码
总结:

在成员变量初始化的时候尽量走初始化列表,在编译器中即使不写出初始化列表大概不在初始化列表中初始化的成员变量,也会自动走初始化列表
当成员变量在声明时写了缺省值时,初始化列表会按照缺省值举行初始化(初始化列表中没有初始化赋值)
以是,以后成员变量初始化时一般都用初始化列表或给缺省值
类型转换

1、C++支持内置类型隐式转换为类类型对象,但必要相应的内置类型的构造函数
在C++11后支持多参数隐式转换
  1. class A
  2. {
  3. public:
  4.     A(int a)
  5.       :_a =a
  6.     {
  7.         
  8.     }
  9.     A(int a1,int a2)
  10.       :_a1(a1)
  11.       ,_a2(a2)
  12.     {
  13.         
  14.     }
  15. private:
  16.     int _a1 = 1;
  17.     int _a2 = 1;
  18. }
  19. int main()
  20. {
  21.     A a=1;
  22.     const A& a1 = 1;
  23.     A a2(1,2);
  24.     return 0;
  25. }
复制代码
代码中的隐式类型转换会涉及构造函数和拷贝构造函数,中心产生暂时变量,但颠末编译器的优化,就只会有一个直接构造函数
2、构造函数前面加上explicit就不会支持隐式类型转换
  1. class A
  2. {
  3. public:
  4.     explicit A(int a)//加上explicit关键字
  5.       :_a1(a)
  6.     {
  7.         
  8.     }
  9. private:
  10.     int _a1 = 1;
  11. };
  12. int main()
  13. {
  14.     A a=1;
  15.     return 0;
  16. }
复制代码

3、类与类之间也可以举行隐式类型转换,但也必要对应的构造函数支持
它的原理与内置类型隐式类型转换为自界说类型雷同
  1. class A
  2. {
  3. public:
  4.     //explicit A(int a)//加上explicit关键字,就不支持隐式类型转换
  5.     A(int a)//内置类型与自定义类型
  6.         :_a(a)
  7.     {
  8.     }
  9.     int Get() const
  10.     {
  11.         return _a;
  12.     }
  13. private:
  14.     int _a = 1;
  15. };
  16. class B
  17. {
  18. public:
  19.         B(const A& a)
  20.                 :_b(a.Get())
  21.         {}
  22. private:
  23.         int _b = 0;
  24. };
  25. int main()
  26. {
  27.     A a = 1;
  28.     B b = a;
  29.     return 0;
  30. }
复制代码
static成员

静态成员的调用:
 


静态成员变量:

1、

用static关键字修饰的成员变量被称为静态成员变量,静态成员变量在类内声明,但必须在类外初始化
  1. class A
  2. {
  3. public:
  4. private:
  5.         //类中声明
  6.         static int a;
  7. };
  8. //类外初始化
  9. int A::a = 1;
复制代码
2、

静态成员变量是属于全部该类的对象的,而不是专属于某一个对象,它不存在对象中,存放于静态区

3、


静态成员变量不能在声明处给缺省值,因为静态成员变量不走初始化列表,由前文可知:给成员变量的缺省值是给初始化列表
  1. class A
  2. {
  3. public:
  4. private:
  5.         //类中声明
  6.         static int a;
  7.         //static int a = 1;//error:不能再类中初始化
  8. };
  9. //类外初始化
  10. int A::a = 1;
复制代码
静态成员函数:

1、

用static修饰的成员函数,它没有this指针,而且它不能使用类型限定符
2、

因为它没有this指针,以是它只可以访问静态成员函数和静态成员变量,非静态成员是不能访问的
3、

非静态成员可以恣意访问静态成员
注:静态成员也受访问限定符的限制

代码:

  1. class A
  2. {
  3. public:
  4.         A()
  5.         {
  6.                 a++;
  7.         }
  8.         void Print() const
  9.         {
  10.                 cout << a << endl;
  11.         }
  12.         //static int GetA() const//静态成员函数不能使用类型限定符
  13.         static int GetA()
  14.         {
  15.                 return a;
  16.         }
  17. private:
  18.         //类中声明
  19.         static int a;
  20.         //static int a = 1;//error:不能再类中初始化
  21. };
  22. //类外初始化
  23. int A::a = 1;
  24. int main()
  25. {
  26.         /*cout << A::a << endl;*/
  27.         cout << A::GetA() << endl;
  28.         A a1;
  29.         a1.Print();
  30.         cout << a1.GetA() << endl;
  31.         A a2;
  32.         a2.Print();
  33.         return 0;
  34. }
复制代码
友元

1、友元提供了⼀种突破类访问限定符封装的⽅式,友元分为:友元函数和友元类,在函数声明大概类声明的前⾯加friend,并且把友元声明放到⼀个类的⾥⾯。
2、外部友元函数可访问类的私有和保护成员,友元函数仅仅是⼀种声明,他不是类的成员函数
3、友元函数可以在类界说的任何地⽅声明,不受类访问限定符限制。
4、⼀个函数可以是多个类的友元函数。
5、友元类中的成员函数都可以是另⼀个类的友元函数,都可以访问另⼀个类中的私有和保护成员。
6、友元类的关系是单向的,不具有交换性,⽐如A类是B类的友元,但是B类不是A类的友元。
7、友元类关系不能传递,如果A是B的友元, B是C的友元,但是A不是C的友元。
内部类

这一部分了解就可以了
一个类被界说在另一个类中,就叫做内部类
  1. class A
  2. {
  3. public:
  4.         class B//内部类
  5.         {
  6.         };
  7. };
  8. int main()
  9. {
  10.         A::B b1;
  11.         return 0;
  12. }
复制代码
内部类是一个独立的类,它和界说在全局的类的相比就只是会被外部类的类域和访问限定符的限制,以是外部类实例化的类中不包含内部类

内部类在C++中用的比较少,在Java中用得较多
匿名对象

特点:

1、

用类型界说出来的对象就叫做匿名对象,而我们之前界说的类型对象是叫有名对象
  1. A();//匿名对象
复制代码
2、

匿名对象的生命周期只在当前这一行,如果当必要暂时界说一个对象使用,就可以界说匿名对象
3、使用场景

   1、在调用成员函数时:
  1. class A
  2. {
  3. public:
  4.         int f1()
  5.         {
  6.                 return _a;
  7.         }
  8. private:
  9.         int _a = 1;
  10. };
  11. int main()
  12. {
  13.         //之前
  14.         A a1;
  15.         cout << a1.f1() << endl;
  16.         //使用匿名对象
  17.         cout << A().f1() << endl;
  18.         return 0;
  19. }
复制代码
2、做缺省参数
  1. void f2(const A& a = A())//做缺省值
  2. {
  3. }
复制代码
4、

匿名对象具有常性
  1. class A
  2. {
  3. public:
  4.         A()
  5.         :_a(1)
  6.         {
  7.         }
  8. private:
  9.         int _a;
  10. };
  11. int main()
  12. {
  13.     const A& a1 = A();
  14.         return 0;
  15. }
复制代码
5、匿名对象和暂时对象的区别

匿名对象是我们主动创建的,而暂时对象是编译器创建的




免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

王國慶

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表