为了能到远方,脚下的每一|

nxgy

园龄:6年2个月粉丝:0关注:9

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\n", s);
      ms = s;
      }
      ~Member() {
      printf("~Member(): %s\n", ms);
      }
      };
      class Test
      {
      Member mA;
      Member mB;
      public:
      Test() : mB("mB"), mA("mA") {
      printf("Test()\n");
      }
      ~Test() {
      printf("~Test()\n");
      }
      };
      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\n",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\n",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\n", this);
      }
      int main()
      {
      Test t1(1);
      Test t2(2);
      Test t3(3);
      printf("t1.getMi() = %d\n", t1.getMi()); // t1.getMi() = 1
      printf("&t1 = %p\n", &t1); // &t1 = 0xbf975fd4
      t1.print(); // this = 0xbf975fd4
      printf("t2.getMi() = %d\n", t2.getMi()); // t2.getMi() = 2
      printf("&t2 = %p\n", &t2); // &t2 = 0xbf975fdc
      t2.print(); // this = 0xbf975fdc
      printf("t3.getMi() = %d\n", t3.getMi()); // t3.getMi() = 3
      printf("&t3 = %p\n", &t3); // &t3 = 0xbf975fe4
      t3.print(); // this = 0xbf975fe4
      return 0;
      }

本文作者:nxgy

本文链接:https://www.cnblogs.com/bky-hbq/p/13720526.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   nxgy  阅读(122)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起