c++中的对象的构造顺序与析构顺序

问题一

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

一.单个函数创建时构造函数的调用顺序

1.调用父类的构造过程
2.调用成员变量的构造函数(调用顺序与声明顺序相同)
3.调用类自身的构造函数

而析构函数与对应构造函数的调用顺序相反!多个对象析构时析构顺序与构造顺序想反。

下面分析一段简单的代码:

#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 gA(“gA”),然后是局部变量:Member mA; Member mB,注意mA和mB这两个变量得顺序不要被 Test() : mB(“mB”), mA(“mA”)这里的定义顺序搞混了,我们的构造顺序是声明的顺序,而不是定义的顺序,那里的定义的顺序是为了给我们造成混淆的,定义的顺序可以随便改变!接着就是调用类自身的构造函数,Test(),它会执行printf(“Test()\n”);
好了,到这一步,说明构造函数调用完成。调用的顺序为:gA,mA,mB,Test().

而析构函数与构造函数的调用顺序相反,所以析构函数的调用顺序为:~Test(), mB, mA, gA.

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

问题二

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

我们知道,在c++中,const可以修饰一个只读变量,也可以修饰一个真正意义上的常量。那么它能否修饰类的对象呢?我们知道类只不过是由struct演变而来的一种用户自定义的数据类型,从某种意义上来讲,它也是一个变量,既然是变量,那么能不能用const修饰它呢?
答案是肯定的!
1.const关键字能够修饰对象
2.const修饰的对象为只读对象
3.只读对象的成员变量不允许被改变
3.只读对象是编译阶段的概念,运行时无效
下面介绍一下C++中const成员函数的定义:

Type ClassName::function(Type p) const

类中的函数声明与实际的函数定义都必须带有const关键字。文字太多不如直接上代码:

#include <stdio.h>class Test
{int mi;
public:Test(int i);Test(const Test& t);int getMi();
};Test::Test(int i)
{mi = i;
}Test::Test(const Test& t)
{mi = t.getMi();  //能否编译通过?
}int Test::getMi()
{return mi;
}int main()
{const Test t(1);t.mi = 100; //能否编译通过?printf("t.getMi() = %d\n",t.getMi()); //能否编译通过?如何才能编译通过?return 0;
}

我把程序放到linux中进行编译,很显然编译不通过,显示的错误有哪些呢?

test.cpp: In copy constructor ‘Test::Test(const Test&)’:
test.cpp:19: error: passing ‘const Test’ as ‘this’ argument of ‘int Test::getMi()’ discards qualifiers
test.cpp: In function ‘int main()’:
test.cpp:5: error: ‘int Test::mi’ is private
test.cpp:31: error: within this context
test.cpp:31: error: assignment of data-member ‘Test::mi’ in read-only structure
test.cpp:33: error: passing ‘const Test’ as ‘this’ argument of ‘int Test::getMi()’ discards qualifiers

首先mi = t.getMi();无法编译通过,因为Test::Test(const Test& t)中的的参数为const的引用,const成员函数只能调用const成员函数。
然后t.mi = 100;编译不通过,因为int Test::mi’ is private,并且‘Test::mi’ in read-only structure,因为我们定义的是const成员函数const Test t(1);这才是我们想说的真正原因。
其次printf("t.getMi() = %d\n",t.getMi());编译不通过 ,因为成员t在上面被定义的是const类型。 那么,该如何让它编译通过呢?在int getMi();函数后面加上const变为

int getMi()const;

int Test::getMi()后面加上const变为

`int Test::getMi()const`

那么这条语句 printf("t.getMi() = %d\n",t.getMi());就可以编译通过了!!!
此时如果在函数int Test::getMi()中加入 mi = 2;则编译又不会通过了,因为该函数已经被定义为const类型,不能改写成员变量的值了!!!
由以上代码的实际试验得出具体结论如下:

C++中const成员函数的特性:

  • const const对象只能调用const成员函数;
  • const 成员函数中只能调用const成员函数;
  • const 成员函数中不能直接改写成员变量的值。

【C++深度剖析教程1】C++中的经典问题解析-c++中的对象的构造顺序与析构顺序相关推荐

  1. C++中对象的构造顺序和析构顺序

    文章目录 1 C++中单个对象的构造和析构顺序 1.1 单个对象的构造和析构顺序 2 C++中多个对象的构造和析构顺序 2.1 局部对象的构造顺序 2.2 堆对象的构造顺序 2.3 全局对象的构造顺序 ...

  2. 【C++深度剖析教程25】继承中的构造与析构

    今天来学习C++中继承的构造与析构,有兴趣一起学习的加qq:1126137994 1.问题 如何初始化父类成员?父类构造函数与子类构造函数有什么关系? 子类对象是如何构造的? 子类中可以定义构造函数 ...

  3. 【C++深度剖析教程30】C++中抽象类和接口

    加qq1126137994 微信:liu1126137994 1.面向对象中的抽象概念; 在现实中,需要知道具体的图形类型才能知道如何求面积,但是对于抽象的'图形',我们是没法求其面积的,而且对其求面 ...

  4. 【C++深度剖析教程39】实现C++数组类模板

    上一篇文章在那个学习了多参数类模板与特化的分析:点击链接查看上一篇文章:类模板深度剖析 本篇文章学习记录: 数值型模板参数 实现C++数组类模板 1.模板中的数值型参数 模板参数可以是数值型参数.也就 ...

  5. 【C++深度剖析教程27】多态的概念与意义

    今天来学习一个新的概念,多态!!!多态在C++编程中具有重要的地位与意义,是面向对象的一个重要思想! 加qq1126137994一起学习更多技术~ 1.问题引入 父类与子类之间具有赋值兼容性; *子类 ...

  6. 【C++深度剖析教程26】父子间的冲突

    今天继续来学习C++,父类与子类之间的冲突.加qq1126137994共同学习交流. 1.问题 子类中是否可以定义父类中的同名成员,如果可以,如何区分?如果不可以那又为什么? 2.问题的延伸 子类可以 ...

  7. 【C++深度剖析教程7】C++之类中的函数重载

    函数重载的回顾(接上一篇文章): 函数重载的本质为相互独立的不同的函数 C++中通过函数名和函数参数确定函数调用 无法直接通过函数名得到重载函数的入口地址 函数重载必然发生在同一个作用域中 类中的成员 ...

  8. 【C++深度剖析教程34】C++中的强制类型转换dynamic_cast

    加qq1126137994 微信:liu1126137994 一起学习更多技术!!! C++中的继承中,如何使用强制类型转换? 知识点: dynamic_cast是与继承相关的类型转换关键字 dyna ...

  9. 【C++深度剖析教程33】C++中的构造函数与析构函数是否可以为虚函数

    加qq1126137994 微信:liu1126137994 一起学习更多技术!!! 问题一:构造函数与析构函数可以成为虚函数么? 答案: 1.构造函数不可以成为虚函数 因为在构造函数执行结束后,虚函 ...

最新文章

  1. 他是娱乐圈最低调的人,甘当多年绿叶,没想到竟是鲁迅的侄子
  2. P1634 禽兽的传染病
  3. vim C plugins
  4. Android地图 总于实现了!
  5. linux 下 gcc o2优化可能出现的问题
  6. 手把手教你用java读写excel表格文件(POI,EasyExcel)
  7. 插件怎么用_【Anki插件篇】(01)插件介绍
  8. c语言宏定义替换字符串,C语言中,宏替换的替换规则
  9. Extjs 之dataview布局
  10. 将文件转成base64 字符串
  11. 用html制作简单考试系统,巧用EXCEL制作模拟考试系统
  12. C++控制台游戏-小镇物语正式版 V1.7.21BUG修复版【可存档!!!】
  13. 揭秘淘宝286亿海量图片存储与处理架构,海量小文件存储的解决方案
  14. 差分技术:LVDS(低电压差分信号)
  15. windows如何查看自己的ip地址
  16. 读大学,大学四年培养的思维与工作能力,(读研,读博)
  17. jbpm 历史查询笔记
  18. Nokia5233手机和我装的几个symbian V5手机软件
  19. 【马士兵】Python基础--01
  20. 选硬盘时,该选择SSD/SATA/SAS哪个好?

热门文章

  1. 最近写的一个qt应用软件
  2. CSS之七个高度有效的媒体查询技巧
  3. 聊一聊CSS中的死循环
  4. mysql的命令行安装,忘记密码,密码重置问题
  5. mysql 内置功能 函数 date_format函数
  6. C#前后端操作json数据
  7. javaweb引用serverlet库
  8. string、stringbuilder、stringbuffer区别
  9. OSError: [Errno 1] Operation not permitted 问题解决
  10. ABAP 弹出框自建内容POPUP