欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C++中的析构顺序和cosnt对象

程序员文章站 2022-04-09 08:39:39
析构顺序、const对象、const成员函数、const成员变量 ......

1,当程序中存在多个对象的时候,如何确定这些对象的析构顺序?

 

2,单个对象创建时构造函数的调用顺序(工程经验总结):

    1,调用父类的构造过程;

    2,调用成员变量的构造函数(调用顺序与声明顺序相同);

       1,某个类的成员是其它类的对象;

    3,调用类自身的构造函数;

       1,析构函数与对应构造函数的调用顺序相反;

   

3,多个对象析构时:

    1,构造顺序与析构顺序相反;

   

4,构造与析构顺序实例分析:

 1 #include <stdio.h>
 2 
 3 class member
 4 {
 5     const char* ms;
 6     
 7 public:
 8     member(const char* s)
 9     {
10         printf("member(const char* s): %s\n", s);
11         
12         ms = s;
13     }
14     
15     ~member()
16     {
17         printf("~member(): %s\n", ms);
18     }
19 };
20 
21 class test
22 {
23     member ma;
24     member mb;
25     
26 public:
27     test() : mb("mb"), ma("ma")
28     {
29         printf("test()\n");
30     }
31     
32     ~test()
33     {
34         printf("~test()\n");
35     }
36 };
37 
38 member ga("ga");
39 
40 int main()
41 {
42     test t;  // ga
43              // ma
44              // mb
45              // test()
46              // ...
47              //~test()
48              // mb
49              // ma
50              // ga
51     
52     return 0;
53 }

   

5,对于栈对象和全局对象,类似于入栈与出栈的顺序,最后构造的对象最先析构;堆对象的析构发生在使用 delete 的时候,与 delete 的顺序相关;

  

6,const 关键字能否修饰类的对象?如果可以,有什么特性?

    1,const 关键字能够修饰对象;

       1,类也是用户自定义的数据类型,类是从 struct 进化而得到的一个全新关键字,struct 专门用来定义结构体,其定义的结构体在 c 语言中依旧是变量,既然是变量,就可以被 cosnt 所修饰;

       2,对应的,对象在某种角度也是变量,所以也可以被 const 修饰;

    2,const 修饰的对象为只读对象;

       1,这是唯一的可能性;

    3,只读对象的成员变量不允许被改变;

       1,对象就是由一系列的成员变量构成的,对象已经是只读的了,也就意味着成员变量是不允许被改变的;

    4,只读对象是编译阶段的概念,运行时无效;

       1,只读对象起始还是可以被改变的;

   

7,c++ 中的 const 成员函数:

    1,const 对象只能调用 const 的员函数;

       1,因为 const 对象的 this 指针是底层常量,不能拷贝给非 const 的成员函数的 this 指针,因为后者的 this 是变量,这会改变 const *this 的属性,造成其指向的对象会被改变;

    2,const 成员函数中只能调用 const 成员函数;

       1,底层 const 指针不能拷贝给非 const 指针;

    3,const 成员函数中不能直接改写成员变量的值;

       1,const 成员函数只能被 const 对象调用,而此时其成员函数也底层 const 的,不能修改底层 const 指针指向的变量;

    4,const 成员函数特殊的意义是被只读对象调用;

       1,底层 const 指针不能拷贝给非 const 指针;

   

8,const 成员函数的定义:

    1,type classname::function(type p) const

       1,声明之后,函数体之前;

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

   

9,类的 const 函数初探编程实验:

 1 #include <stdio.h>
 2 
 3 class test
 4 {
 5     int mi;
 6 public:
 7     int mj;
 8 
 9     test(int i);
10     test(const test& t);
11     int getmi() const;
12 };
13 
14 test::test(int i)
15 {
16     mi = i;
17 }
18 
19 test::test(const test& t)
20 {
21     // mi = t.getmi(); getmi() 非常函时,t 是对象的常引用,t 这个对象代表的引用代表只读对象,只能调用 const 函数;
22     mi = t.mi;  // 这个时候可以,mi 是私有的,能够通过点操作符来访问吗?不是说只有对象自己的成员函数才可以访问自己的成员变量吗?这就引出了本文10中的问题;
23 }
24     
25 int test::getmi() const 
26 {
27     // mi = 2; 这里出错,不能够修饰 mi 的值;
28     return mi;
29 }
30 
31 int main()
32 {
33     test t(1);
34     
35     const test t1(1);  // 实际工程开发中,并不一定每一个成员函数都是 const 的,这就意味着很少使用 const 对象,所以 一般情况都不用定义 const 成员函数;
36     
37     t1.mj = 1000;  // 不能给只读变量 mj 赋值;const 修饰对象后,得到只读对象,其对应的成员变量值是不可以被改变的;只读变量:编译阶段不能出现在赋值符号左边,运行时能够改变;
38                    
39     printf("t.getmi() = %d\n", t.getmi());  // 编译器显示 getmi() 是不可以被调用的,因为这个时候 t 是只读对象,但是 getmi() 这个时候不是 const 函数,加上后则可以了;
40     
41     return 0;
42 }

   

10,成员函数和成员变量都是隶属于具体对象的吗?

    1,每一个对象都拥有自己的一套成员变量,但是所有的对象共享一套成员函数;

 

11,从面向对象的角度:

    1,对象由属性(成员变量)和方法(成员函数)构成;

    从程序运行的角度:

       1,对象由数据和函数构成:

           1,数据可以位于栈、堆和全局数据区;

           2,函数只能位于代码段;

              1,代码段是只读的,在程序运行过程中是不可以被改变的,当编译器将最终的可执行程序编译好之后,代码段就被确定了,不可以被该;

              2,对象可以动态的创建、动态的删除,对于数据而言,可以做到,栈数据、堆数据都可以动态的创建出来、动态的删除掉,但对于代码不可能;

              3,在面相对象里面,由于程序的特性,天生的决定了成员函数是不能每个对象都有一套的,只可能是所有的对象共享一套成员函数,因为代码段是不可以动态的添加和删除的;

          

12,结论:

    1,每一个对象拥有自己独立的属性(成员变量);

    2,所有的对象共享类的方法(成员函数);

    3,方法能够直接访问对对象的属性;

    4,方法中的隐藏参数 this 用于指代当前对象;

       1,所有的对象都可以调用一套成员函数,函数本身如何知道是那个对象调用的呢?

       2,成员函数(和普通函数区别在于其多了一个隐藏的参数 this)分辨不同对象通过 this 指针来分辨;

       3,this 指针通过接受不同的对象传来的地址来给成员函数分辨对象;

           1,所以 const 函数只能调用 const 函数是因为要传递个被调用对象的 this 指针,但是调用函数的底层 const this 指针只能拷贝给被调用对象的底层 const this 指针;

   

13,成员函数的秘密编程实验:

 1 #include <stdio.h>
 2 
 3 class test
 4 {
 5     int mi;
 6 public:
 7     int mj;
 8     test(int i);
 9     test(const test& t);
10     int getmi();
11     void print();  // 加这个函数是为了证明所有对象共用一套成员函数;
12 };
13 
14 test::test(int i)
15 {
16     mi = i;
17 }
18 
19 test::test(const test& t)
20 {
21     mi = t.mi;  // 成员函数可以直接访问成员变量,因此拷贝构造函数这个特殊的成员函数就可以直接访问对象的成员变量,所以这里直接访问了 t 这个引用所指代的对象的成员变量是完全合法的;成员函数只有一套,它能直接访问任何所属类对象的成员变量,当然被调用时只传递一个对象的地址;
22                 
23 }
24     
25 int test::getmi()
26 {
27     return mi;
28 }
29 
30 void test::print()
31 {
32     printf("this = %p\n", this);
33 }
34 
35 int main()
36 {
37     test t1(1);
38     test t2(2);
39     test t3(3);
40     
41     printf("t1.getmi() = %d\n", t1.getmi());  // 1
42     printf("&t1 = %p\n", &t1);  // t1 的地址
43     t1.print();  // t1 的地址
44     
45     printf("t2.getmi() = %d\n", t2.getmi());  // 2
46     printf("&t2 = %p\n", &t2);  // t2 的地址
47     t2.print();  // t2 的地址
48     
49     printf("t3.getmi() = %d\n", t3.getmi());  // 3
50     printf("&t3 = %p\n", &t3);  // t3 的地址
51     t3.print();  // t3 的地址
52     
53     return 0;
54 }

    1,实验说明:

       1,在类的成员函数当中,有一个隐含的参数,它是一个指针,并且这个指针的值就是调用这个函数所对应的对象的地址;

       2,也就是 this 指针指向当前对象;

       3,成员函数有一个隐含的参数,这个参数是一个 this 指针,其指向当前对象;

       4,每一个对象都有一套自己的成员变量,对象和对象之间的成员变量是独立的、不同的;但是每一个对象都共享一个类的成员函数;

   

14,小结:

    1,对象的析构顺序与构造顺序相反;

    2,const 关键字能够修饰对象,得到只读对象;

    3,只读对象只能调用 const 成员函数;

    4,所有对象共享类的成员函数;

    5,隐藏的 this 指针用于表示当前对象;