|
大家好,今天再次写c++的文章,首先给各位网友说明一下这段时间为啥都是写c++的文章,没有Linux的文章;原因是这样的,自己立了一个flag,八月份把c++的基本语法全部过完(目前完成三分之一),所以文章过程中我写的可能没有很详细的解释一些概念;所以文章中有不理解的地方,可以私聊我,我会尽力解答好。同时昨天遇到一位刚高考完的网友,人家都这么努力学习,你还打酱油吗?
一、对象的析构顺序: 在上一篇文章里面,已经介绍过对象的构造顺序,既然有对象的产生,那么就会有对象的消亡;换句话说,有资源的分配,最终系统就要收回这些分配出去的资源。所以也就有了对象的析构顺序用法了。下面我们来看一下对象析构顺序的分类,不过这里我们先来看构造对象调用构造函数的来引出对象析构的顺序: (1)单个对象创建时构造函数的调用顺序: 引出:析构函数与对应的构造函数的调用顺序相反,也就是对象构造与对象析构(消亡)的顺序相反。 (2)代码演示: - <font style="background-color:rgb(255, 255, 255)"><font face="Tahoma"><font color="black">
- #include <stdio.h>
- class Test
- {
- const char * i;
- public:
- Test(const char *s)
- {
- printf("Test(const char *s) is %s\n",s);
- i=s;
- }
- ~Test()
- {
- printf("~Test() is %s\n",i);
- }
- };
- class Test2
- {
- Test mA;
- Test mB;
- public:
- Test2():mB("mB"),mA("mA")
- {
- printf("Test2()\n");
- }
- ~Test2()
- {
- printf("~Test2()\n");
- }
- };
- Test gA("gA");
- int main()
- {
- Test2 t;
- return 0;
- }
- </font></font></font>
复制代码演示结果: - <font style="background-color:rgb(255, 255, 255)"><font face="Tahoma"><font color="black">
- Test(const char *s) is gA
- Test(const char *s) is mA
- Test(const char *s) is mB
- Test2()
- ~Test2()
- ~Test() is mB
- ~Test() is mA
- ~Test() is gA</font></font></font>
复制代码说明:从运行结果,我们可以看到先触发全局对象的构造函数,然后是触发初类Test2里面的mA和mB对象的构造函数,最后 触发局部对象的构造函数,然后进行析构,我们可以看到,析构顺序完全和构造顺序相反。非常类似于栈的操作规则,栈是先入栈,却是最后出栈。 二、const关键字可以修饰类的对象嘛? 1、这个问题答案肯定是可以修饰的,为啥这么说呢?不知大家还是记得c语言里面的struct关键字不,在之前的文章里面也学习过,使用struct关键字也可以来构造类名,只不过他的所有成员都是公开的(public);换句大家好理解的话,就是结构体,那么在c语言里面,const关键字肯定是可以修饰结构体变量的,当然在c++里面肯定也是可以的,c++不是取代c语言的,而是对c语言进行扩展着,并且兼容c语言的。不过const修饰的对象有啥特性呢? const修饰的对象特性: const修饰的对象为只读对象 只读对象的成员变量不允许被改变 只读对象是编译阶段的概念,运行时无效
代码示例: - <font style="background-color:rgb(255, 255, 255)"><font face="Tahoma"><font color="black">
- #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 t1(1);
- t1.mj = 100;
- printf("the t1.mj is %d\n",t1.mj);
- return 0;
- }</font></font></font>
复制代码
运行结果:
- test.cpp: In function ‘int main()’:
- test.cpp:34:10: error: assignment of member ‘Test::mj’ in read-only object
- t1.mj = 100;
复制代码
分析:我们可以看出public里面的属性mj是不能修改的,为只读的,因为类对象被const修饰了。 2、const成员函数: 其实以前在写初始化列表的文章之前,以前提到过const修饰的成员属性(不过这个属性是私密的),我们只能用初始化列表对其进行初始化;提这个的原因是;也算是复习一下;同时说的直白一点,咋们刚才讲解完了const修饰的对象,同时用该对象访问的类成员属性是不能修改的;现在我们当然会想到const成员函数了,一环扣一环嘛(我不说,你看到这里也会有好奇心!);下面我们来看一下const成员函数的定义和规则: (1)定义: - <font style="background-color:rgb(255, 255, 255)"><font face="Tahoma"><font color="black">
- Type ClassName::function(Type p)const
- 类中的函数声明与实际函数定义中都必须带const关键字,注意const是函数结尾</font></font></font>
复制代码(2)规则: const对象只能调用const的成员函数,不能调用普通的成员函数,例如: - <font style="background-color:rgb(255, 255, 255)"><font face="Tahoma"><font color="black">
- #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 t1(1);
- printf("the mi is %d\n",t1.getMi());
- return 0;
- }</font></font></font>
复制代码演示结果:
- test.cpp: In function ‘int main()’:
- test.cpp:34:42: error: passing ‘const Test’ as ‘this’ argument discards qualifiers [-fpermissive]
- printf("the mi is %d\n",t1.getMi());
- ^
- test.cpp:23:6: note: in call to ‘int Test::getMi()’
- int Test::getMi()
- ^~~~
复制代码
我们可以看到const修饰的类对象调用普通成员函数报错,现在我们把普通成员函数getMi()改成const成员函数:
- #include <stdio.h>
- class Test
- {
- int mi;
- public:
- int mj;
- Test(int i);
- Test(const Test& t);
- int getMi() const;
- };
- Test::Test(int i)
- {
- mi = i;
- }
- Test::Test(const Test& t)
- {
- }
- int Test::getMi() const
- {
- return mi;
- }
- int main()
- {
- const Test t1(1);
- printf("the mi is %d\n",t1.getMi());
- return 0;
- }
复制代码
这样的话就可以编译通过了,哈哈。 const成员函数不能直接修改成员变量的值:
- #include <stdio.h>
- class Test
- {
- int mi;
- public:
- int mj;
- Test(int i);
- Test(const Test& t);
- int getMi() const;
- };
- Test::Test(int i)
- {
- mi = i;
- }
- Test::Test(const Test& t)
- {
- }
- int Test::getMi() const
- {
- mj = 89;
- return mi;
- }
- int main()
- {
- const Test t1(1);
- printf("the mi is %d\n",t1.getMi());
- return 0;
- }
复制代码
运行结果:
- root@txp-virtual-machine:/home/txp# g++ test.cpp
- test.cpp: In member function ‘int Test::getMi() const’:
- test.cpp:25:10: error: assignment of member ‘Test::mj’ in read-only object
- mj = 89;
复制代码
const 成员函数中只能调用 const 成员函数: - <font style="background-color:rgb(255, 255, 255)"><font face="Tahoma"><font color="black">
- #include <stdio.h>
- class Test
- {
- int mi;
- public:
- int mj;
- Test(int i);
- Test(const Test& t);
- int getMi() const;
- int getMj() const;
- };
- Test::Test(int i)
- {
- mi = i;
- }
- Test::Test(const Test& t)
- {
- }
- int Test::getMj() const
- {
- return mj;
- }
- int Test::getMi() const
- {
- getMj();
- return mi;
- }
- int main()
- {
- const Test t1(1);
- printf("the mi is %d\n",t1.getMi());
- return 0;
- }</font></font></font>
复制代码3、搞清楚成员函数和成员变量是否都是隶属于具体对象 4、this指针 不知大家是否注意到在拷贝构造函数里面的这条语句,参数里面是引用,那么t也相当于是一个对象,所以会有t.mi这样的写法,这里要明白:
- Test(const Test& t)
- {
- mi = t.mi;
-
- }
复制代码
所以这里我就引出了this指针,他表示方法中的隐藏参数代指当前对象,为了说明这个,下面我们来看一个代码示例: - <font style="background-color:rgb(255, 255, 255)"><font face="Tahoma"><font color="black">
- #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;
- }
-
- 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());
- printf("&t1 = %p\n", &t1);
- t1.print();
-
- printf("t2.getMi() = %d\n", t2.getMi());
- printf("&t2 = %p\n", &t2);
- t2.print();
-
- printf("t3.getMi() = %d\n", t3.getMi());
- printf("&t3 = %p\n", &t3);
- t3.print();
-
- return 0;
- }</font></font></font>
复制代码输出结果: - <font style="background-color:rgb(255, 255, 255)"><font face="Tahoma"><font color="black">
- root@txp-virtual-machine:/home/txp# ./a.out
- t1.getMi() = 1
- &t1 = 0x7ffec3f5e750
- this = 0x7ffec3f5e750
- t2.getMi() = 2
- &t2 = 0x7ffec3f5e758
- this = 0x7ffec3f5e758
- t3.getMi() = 3
- &t3 = 0x7ffec3f5e760
- this = 0x7ffec3f5e760</font></font></font>
复制代码分析: 三、总结: 对象的析构顺序与构造顺序相反 const 关键字能够修饰对象,得到只读对象 只读对象只能调用 const 成员函数 所有对象共享类的成员函数 隐藏的 this 指针用于表示当前对象
好了,今天的分享就到这里,如果文章中有错误或者不理解的地方,可以交流互动,一起进步。
|