• (3.1)狄泰软件学院C++课程学习剖析二


                                                                                     深度剖析C++第二部分

    1、通过对象名能够访问public成员变量。每个对象的成员变量都是专属的,成员变量不能够在对象之间共享。

    2、需求:统计在程序运行期间某个类的对象数目,保证程序的安全性(不能使用全局变量),随时可以获取当前对象的数目。

     (1)使用全局变量的情况

    1. #include <iostream.h>
    2. #include <stdio.h>
    3. int count;
    4. int getCount()
    5. {
    6. return count;
    7. }
    8. class Test{
    9. public:
    10. Test()
    11. {
    12. count++;
    13. }
    14. ~Test()
    15. {
    16. --count;
    17. }
    18. };
    19. Test t0;
    20. Test t1;
    21. int main(int argc, char *argv[])
    22. {
    23. Test t;
    24. printf("count:%d ",getCount());
    25. return 0;
    26. }

    (2)使用static变量的情况

    1. #include <iostream.h>
    2. #include <stdio.h>
    3. class Test{
    4. private:
    5. static int count; //静态成员变量
    6. public:
    7. Test()
    8. {
    9. count++;
    10. }
    11. ~Test()
    12. {
    13. --count;
    14. }
    15. static int getCount() //静态成员函数
    16. {
    17. //printf("count:%d ",count);
    18. return count;
    19. }
    20. };
    21. int Test::count=0; //类的静态成员变量必须先初始化再使用 另外占用空间(全局数据区空间)
    22. Test t0;
    23. Test t1;
    24. int main(int argc, char *argv[])
    25. {
    26. Test t;
    27. printf("count:%d ",Test::getCount());
    28. //t.getCount();
    29. return 0;
    30. }

    3、关于类的静态成员变量,通常情况下都是定义为public的,因为静态成员变量的生命周期不依赖于任何一个对象,静态成员变量属于整个类所有,所有对象共享类的静态成员变量,我们可以通过类名直接访问公有静态成员变量,也可以通过对象名访问公有静态成员变量。

    因为静态成员变量不属于某一个特定的对象所有,所以他不能分配在 对象空间上,因此它需要在类外单独分配空间,它的存储在全局数据区。静态成员变量的生命期为程序运行期。类中可以通过static关键字定义静态成员变量。

    在C++中,静态成员是属于整个类的而不是某个对象,静态成员变量只存储一份供所有对象共用。所以在所有对象中都可以共享它。使用静态成员变量实现多个对象之间的数据共享不会破坏隐藏的原则,保证了安全性还可以节省内存。

    不能通过类名来调用类的非静态成员函数,只能调用类的静态成员函数和静态成员变量。类的对象可以使用静态成员函数和非静态成员函数。静态成员函数中不能引用非静态成员(因为静态成员函数属于整个类,在类实例化对象之前就已经分配空间了,而类的非静态成员必须在类实例化对象后才有内存空间,所以这个调用就出错了,就好比没有声明一个变量却提前使用它一样。);类的非静态成员函数可以调用用静态成员函数,但反之不能。类的静态成员变量必须先初始化再使用。

    对类的静态成员变量和成员函数作个总结:

    一。静态成员函数中不能调用非静态成员。

    二。非静态成员函数中可以调用静态成员。因为静态成员属于类本身,在类的对象产生之前就已经存在了,所以在非静态成员函数中是可以调用静态成员的。

    三。静态成员变量使用前必须先初始化(如int MyClass::m_nNumber = 0;),否则会在linker时出错

    参考博客:http://blog.csdn.net/morewindows/article/details/6721430

    静态成员函数只能访问静态成员变量或静态成员函数,而不能访问普通成员函数,因为静态成员函数在对象构造前就已经分配 了存储空间。

    静态成员函数可以通过类名直接访问,也可以通过对象名直接访问,静态成员函数没有隐藏的this参数。

    4、二阶构造模式   参考博客:http://blog.csdn.net/lgc_lg/article/details/54783242

    构造函数中可以使用return语句,构造函数执行结束不一定说明对象就构造成功了。构造函数只是决定对象的初始状态,而不能决定对象的诞生。半成品对象:构造函数的初始化过程不能按照预期的计划完成构造而形成的对象,半成品对象也是合法的c++对象,但也是BUG的重要来源。构造函数中初始化操作失败不影响对象的诞生。

    二阶构造是人为的将初始化过程分为两个部分,二阶构造的根本意义在于保证创建的 对象都是完整初始化的,不存在半成品对象。

    工程开发中的构造过程分为:

    (1)资源无关的初始化操作:不可能出现异常情况的操作

    (2)需要使用系统资源的操作:可能出现异常情况:如 :内存申请、文件访问、定义指针等

    程序代码示例:

    1. #include <stdio.h>
    2. class TwoPhaseCons
    3. {
    4. private:
    5. TwoPhaseCons() // 第一阶段构造函数
    6. {
    7. }
    8. bool construct() // 第二阶段构造函数
    9. {
    10. return true;
    11. }
    12. public:
    13. static TwoPhaseCons* NewInstance(); // 对象创建函数
    14. };
    15. TwoPhaseCons* TwoPhaseCons::NewInstance()
    16. {
    17. TwoPhaseCons* ret = new TwoPhaseCons();
    18. // 若第二阶段构造失败,返回 NULL
    19. if( !(ret && ret->construct()) )
    20. {
    21. delete ret;
    22. ret = NULL;
    23. }
    24. return ret;
    25. }
    26. int main()
    27. {
    28. TwoPhaseCons* obj = TwoPhaseCons::NewInstance();
    29. printf("obj = %p ", obj);
    30. delete obj;
    31. return 0;
    32. }

    5、友元关系发生在函数与类之间或者类与类之间,友元关系是单项的,不能传递。在类中以friend关键字来声明友元,类的友元可以是其他类或者具体函数。友元不是类的一部分,友元不受类中访问级别的限制,友元可以访问具体类的所有成员。在类中用friend关键字对函数或类进行声明

    友元关系不具备传递性,类的友元可以是其他类的成员函数,也可以是某个完整的类。

    代码示例一:类与类之间作为友元

    1. #include<iostream>
    2. #include<stdio.h>
    3. class TestA{
    4. private: friend class TestB;
    5. int j;
    6. public:
    7. TestA()
    8. {
    9. j=11;
    10. }
    11. };
    12. class TestB{
    13. private: friend class TestC;
    14. int i;
    15. public:
    16. TestB()
    17. {
    18. i=10;
    19. }
    20. /* int get(TestA obj) 友元不具有传递性
    21. {
    22. return obj.j;
    23. }
    24. */
    25. };
    26. class TestC{
    27. public:
    28. int get (TestB obj)
    29. {
    30. return obj.i;
    31. }
    32. int get (TestA obj)
    33. {
    34. return obj.j;
    35. }
    36. };
    37. int main()
    38. {
    39. TestC c;
    40. TestB b;
    41. TestA a;
    42. printf("c.get(b)=%d ",c.get(b));
    43. printf("b.get(a)=%d ",b.get(a));
    44. //printf("%d ",c.get(a)); error 友元在类之间不具有传递性
    45. return 0;
    46. }

    代码示例二:成员函数作为一个类的友元

    1. #include<iostream>
    2. #include<stdio.h>
    3. class TestA{
    4. private:
    5. int j;
    6. public:
    7. TestA()
    8. {
    9. j=11;
    10. }
    11. friend int getJ(TestA obj); //友元声明 函数作为一个类的友元
    12. };
    13. int getJ(TestA obj)
    14. {
    15. return obj.j;
    16. }
    17. int main()
    18. {
    19. TestA a;
    20. printf("%d ",getJ(a));
    21. return 0;
    22. }

    代码示例三:

    代码从示例四:

    6、函数重载的本质为相互独立的不同函数,c++中通过函数名和函数参数确定函数调用,所以说无法直接通过函数名得到重载函数的入口地址,函数重载必然发生在同一个作用域中。(类作用域、全局作用域、局部作用域等) 全局函数和成员函数是不能够进行重载关系的。

    构造函数的重载     普通成员函数的重载    静态成员函数的重载   

    函数重载的意义:(1)扩展系统中已经存在的函数功能(2)扩展系统中不存在的功能

    7、操作符重载

    c++中的重载能够扩展操作符的功能,操作符的重载以函数的方式进行,本质是用特殊形式的函数扩展操作符的功能。

    通过operator关键字可以定义特殊的函数,operator的本质是通过函数重载操作符

    操作符重载遵循相同的函数重载规则 ,全局函数和成员函数都可以实现对操作符的重载。

    我有个朋友是爵士音乐家,他有次跟我说:如果你不是乐队里最差的演奏者,马上换支乐队。我现在在Spotify工作,在这里我每天都觉得自己是个【狗屁程序员】,也因此我离开了上一家公司,从Spotify重头开始。当我在这里再也感觉不到自己是个【狗屁程序员】的时候,我会选择离开,然后找一个能让我再次感到自己是坨屎的地方。这种策略在我的职业生涯里确实 帮了我大忙。 ------译自 Quora
  • 相关阅读:
    前后端分离开发中动态菜单的两种实现方案
    Spring Security 前后端分离登录,非法请求直接返回 JSON
    Spring Boot2 系列教程(九)Spring Boot 整合 Thymeleaf
    原创的离线版 Redis 教程,给力!
    Spring Boot2 系列教程(八)Spring Boot 中配置 Https
    Anaconda创建环境、删除环境、激活环境、退出环境
    开源一个功能完整的SpringBoot项目框架
    Spring Boot和Spring Cloud学习资源推荐
    Ubuntu 18.04下安装Steam顶级在线游戏平台
    终极手撕之架构大全:分布式+开源框架+微服务+性能优化,够不够?
  • 原文地址:https://www.cnblogs.com/wycBlog/p/7150336.html
Copyright © 2020-2023  润新知