zoukankan      html  css  js  c++  java
  • 16 经典问题解析二

    1 析构函数调用顺序

    • 【问题】当程序中存在多个对象时,如何确定这些对象的析构顺序?

      • 对于栈对象和全局对象,类似于入栈和出栈的顺序,最后构造的对象被最先析构
      • 堆对象的析构发生在使用 delete 的时候,delete 的使用顺序相关
    • 单个对象创建时构造函数的调用顺序

      • 1.调用父类的构造函数
      • 2.调用成员变量的构造函数(调用顺序与声明顺序相同)
      • 3.调用类自身的构造函数
      • 析构函数与对应构造函数的调用顺序相反
    • 多个对象析构时,析构顺序与构造顺序相反

    • 示例1:构造与析构顺序

      • Demo

        #include <stdio.h>
        
        class Member
        {
            const char* ms;
        public:
            Member(const char* s) {
                printf("Member(const char* s): %s
        ", s);    
                ms = s;
            }
            ~Member() {
                printf("~Member(): %s
        ", ms);
            }
        };
        
        class Test
        {
            Member mA;
            Member mB;
        public:
            Test() : mB("mB"), mA("mA") {
                printf("Test()
        ");
            }
            ~Test() {
                printf("~Test()
        ");
            }
        };
        
        Member gA("gA");
        
        int main()
        {
            Test t;
            
            return 0;
        }
        
      • 编译运行

        Member(const char* s): gA
        Member(const char* s): mA
        Member(const char* s): mB
        Test()
        ~Test()
        ~Member(): mB
        ~Member(): mA
        ~Member(): gA
        

    2 const 对象

    • 【问题】const 关键字能否修饰类的对象,如果可以,有什么特性?

      • const 关键字能够修饰类的对象
      • const 修饰的对象为只读对象
      • 只读对象的成员变量不允许被改变
      • 只读变量是编译阶段的概念,运行时无效
    • const 成员函数的定义

      Type ClassName::function(Tyep p) const

      类中的函数声明与实际函数定义中都必须带 const 关键字

    • C++ 中的 const 成员函数

      • const 对象只能调用 const 的成员函数
      • const 成员函数中只能调用 const 成员函数
      • const 成员函数中不能直接改写成员变量的值
    • 示例2:类的 const 函数

      • Demo1:只读对象的成员变量不允许被改变

        #include <stdio.h>
        
        class Test
        {
            int mi;
        public:
            int mj;
            Test(int i);
            Test(const Test& t);
            int getMi();
        };
        
        Test::Test(int i)
        {
            mi = i;
        }
        
        Test::Test(const Test& t)
        {
            
        }
            
        int Test::getMi()
        {
            return mi;
        }
        
        int main()
        {
            // 定义 const 对象
            const Test t(1);
            t.mj = 1000;
            
            return 0;
        }
        
      • 编译

        test.cpp: In function ‘int main()’:
        test.cpp:31:10: error: assignment of member ‘Test::mj’ in read-only object
             t.mj = 1000;
                  ^
        
      • Demo2:const 对象只能调用 const 的成员函数

        #include <stdio.h>
        
        class Test
        {
            int mi;
        public:
            int mj;
            Test(int i);
            Test(const Test& t);
            int getMi();
        };
        
        Test::Test(int i)
        {
            mi = i;
        }
        
        Test::Test(const Test& t)
        {
            
        }
            
        int Test::getMi()
        {
            return mi;
        }
        
        int main()
        {
            const Test t(1);
            printf("t.getMi() = %d
        ",t.getMi());  // const对象不能调用普通成员函数
            
            return 0;
        }
        
      • 编译

        test.cpp: In function ‘int main()’:
        test.cpp:31:39: error: passing ‘const Test’ as ‘this’ argument discards qualifiers [-fpermissive]
             printf("t.getMi() = %d
        ",t.getMi());
                                               ^
        test.cpp:23:5: note:   in call to ‘int Test::getMi()’
         int Test::getMi()
             ^
        

    3 类成员

    • 【问题】成员函数和成员变量都是隶属于具体对象的么?

    • 从对象对象的角度

      • 对象由属性(成员变量)和方法(成员函数)构成
    • 从程序运行的角度

      • 对象由数据和函数构成
        • 数据可以位于栈,堆和全局数据区
        • 函数只能位于代码段
    • 结论

      • 每一个对象拥有自己独立的属性(成员变量)
      • 所有的对象共享类的方法(成员函数)
      • 类的方法能够直接访问对象的属性
      • 类的方法中的隐藏参数 this 指针(常量指针,始终指向调用当前函数的对象)用于指代当前对象
    • 示例3

      • Demo

        #include <stdio.h>
        
        class Test
        {
            int mi;
        public:
            int mj;
            Test(int i);
            Test(const Test& t);
            int getMi();
            void print();
        };
        
        Test::Test(int i)
        {
            mi = i;
        }
        
        Test::Test(const Test& t)
        {
            mi = t.mi;  //为什么拷贝构造函数可以访问对象t的private成员变量mi?  =>封装是编译期的概念,是针对类型而非对象的,在类的成员函数中可以访问同类型实例对象的私有成员变量
        }
            
        int Test::getMi()
        {
            return mi;
        }
        
        void Test::print()
        {
            printf("this = %p
        ", this);
        }
        
        int main()
        {
            Test t1(1);
            Test t2(2);
            Test t3(3);
            
            printf("t1.getMi() = %d
        ", t1.getMi());  // t1.getMi() = 1
            printf("&t1 = %p
        ", &t1);                // &t1 = 0xbf975fd4
            t1.print();                               // this = 0xbf975fd4
            
            printf("t2.getMi() = %d
        ", t2.getMi());  // t2.getMi() = 2
            printf("&t2 = %p
        ", &t2);                // &t2 = 0xbf975fdc
            t2.print();                               // this = 0xbf975fdc
            
            printf("t3.getMi() = %d
        ", t3.getMi());  // t3.getMi() = 3
            printf("&t3 = %p
        ", &t3);                // &t3 = 0xbf975fe4
            t3.print();                               // this = 0xbf975fe4
            
            return 0;
        }
        
  • 相关阅读:
    初学java
    位操作运算符的最好的解释
    C++手机通讯录排序
    删除TFS项目上的文件
    单元测试中方法运行测试和调试测试不起作用原因
    EF-CodeFirst系列100
    NPOI-Excel系列-1002.创建带有Document Summary Information和Summary Information的Excel文件
    NPOI-Excel系列-1000.创建一个标准的Excel文件
    T4模板批量生成代码文件
    WebService返回json格式数据供苹果或者安卓程序调用
  • 原文地址:https://www.cnblogs.com/bky-hbq/p/13720526.html
Copyright © 2011-2022 走看看