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

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 成员函数中不能直接改写成员变量的值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/423380.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ASP.NET MVC 重点教程一周年版 第七回 UrlHelper 【转】

这节讲 一下ASP.NET MVC中的Helper。 何谓Helper,其实就是在View中为了实现一些灵活功能而写的方法组。 其实ASP.NET MVC的View是Aspx的页面,本身可以声明定义方法,那为什么要有Helper呢&#xff1f; 其实无非是将界面与逻辑分离,而且Asp.net MVC也并不只支持Aspx一种View&…

【C++深度剖析教程2】C++经典问题解析之二 this指针与成员函数

隐藏的this指针&#xff0c;所有对象共享类的成员函数 写一篇博客花费时间虽然长&#xff0c;但是却让你对内容的记忆尤为深刻&#xff0c;尤其是你对它的态度。记录菜鸟的成长日记&#xff0c;也希望同为菜鸟的你们与我一起共同进步&#xff01;&#xff01;现在分享的是C的学…

uml 类图整理

1.五分钟读懂UML类图 http://www.cnblogs.com/shindo/p/5579191.html 2.UML类关系&#xff08;依赖&#xff0c;关联&#xff0c;聚合&#xff0c;组合的区别&#xff09; https://www.jianshu.com/p/eefa0b5b4922 2.1 关联 1、关联关系 关联关系又可进一步分为单向关联、…

web控件开发系列(四) 自定义控件属性(下)

控件在WEB开发时经常要用到&#xff0c;虽然有部分已经存在工具箱里&#xff0c;但有时总需要根据自己的要求&#xff0c;开发一些合适自己的控件。接上一节,已经说过了控件的属性, 例如&#xff0c;我们需要一组属性的集合时&#xff0c;这时我们需要用到的就是复杂属性了&…

【C++深度剖析教程3】C++中类的静态成员变量

学习交流加&#xff08;可免费帮忙下载CSDN资源&#xff09;&#xff1a;个人微信&#xff1a; liu1126137994学习交流资源分享qq群1&#xff08;已满&#xff09;&#xff1a; 962535112学习交流资源分享qq群2&#xff1a; 780902027 以一个简单的例子来引入C中类的静态成员变…

前端学习(46):页面导入样式时,使用link和@import有什么区别?

用法 import的写法 <style type”text/css”> import url&#xff08;“a.css”&#xff09;&#xff1b; </style> link的写法 <link rel"stylesheet" href"index.csss"> 区别 1. 来源&#xff1a;link属于XHTML标签&…

静态变量加载时间,静态代码块加载时间

当类加载器将类加载到JVM中的时候就会创建静态变量&#xff0c;这跟对象是否创建无关。静态变量加载的时候就会分配内存空间。静态代码块的代码只会在类第一次初始化的时候执行一次。一个类可以有多个静态代码块&#xff0c;它并不是类的成员&#xff0c;也没有返回值&#xff…

关于linux系统中无法识别某一命令问题的解决方案

问题描述&#xff1a; [XXXX~]$ su - root 口令&#xff1a; [XXXX:]~# gedit /etc/profile Command gedit is available in /usr/bin/gedit The command could not be located because /usr/bin is not included in the PATH environment variable. -su: gedit&#xff1a;找…

FarMap诞生了!

今天&#xff0c;注册完成的FarMap网站最简版正式上线&#xff0c;开辟了一片我的作品发布空间。www.farmap.cn准备修改各个博客网址和下载地址。FarMap2009 使用说明 关键字&#xff1a;基站定位&#xff0c;CPS&#xff0c;GPS&#xff0c;CPS&GPS&#xff0c;短信通讯&a…

23设计模式学习

1.什么设计模式 1.1模式是解决相似问题的核心1.2设计模式软件设计过程中解决一类问题的方案总结来说&#xff1a;设计模式 &#xff1a;软件设计过程中解决一类问题的一种方案&#xff1b; 2.什么是面向对象的设计模式 面向对象设计模式描述了面向对象设计过程中、特定场景下…

修改linux的最大文件句柄数限制

修改linux的最大文件句柄数限制 对于一般的应用来说(象Apache、系统进程)1024完全足够使用。但是如何象squid、mysql、java等单进程处理大量请求的应用来说就有点捉襟见肘了。如果单个进程打开的文件句柄数量超过了系统定义的值&#xff0c;就会提到“too many files open”的…

人工智能课程

清华大学计算机博士联合智能社创始人年末巨献&#xff0c;【机器学习】大型线上公开课&#xff0c;报名人数超过2800人&#xff0c;课程观看地址&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1nv66ywD 密码&#xff1a;9bv3想看更多课程的联系:qq:1126137994微信&…

Makefile工程管理语法与使用技巧

使用GNU Make工具来管理程序是每个Linux工程师必须掌握的技能。Make能够使整个程序的编译、链接只需要一个命令(make)就可以完成。 Make的工作主要依赖于一个叫为Makefile的件。Makefile文件描述了整个程序的编译&#xff0c;连接等规则。其中包括&#xff1a;工程中的哪些源文…

JUC 知识总结

在 ThreadPoolExecutor 里面定义了 4 种 handler 策略&#xff0c;分别是 1. CallerRunsPolicy &#xff1a;这个策略重试添加当前的任务&#xff0c;他会自动重复调用 execute() 方法&#xff0c;直到成功。 2. AbortPolicy &#xff1a;对拒绝任务抛弃处理&#xff0c;并且…

C# java 有关“字节序”的描述 .

有关“字节序”的描述 收藏 BIG-ENDIAN&#xff08;大字节序、高字节序&#xff09; LITTLE-ENDIAN&#xff08;小字节序、低字节序&#xff09; 主机字节序 网络字节顺序 JAVA字节序 1&#xff0e;BIG-ENDIAN、LITTLE-ENDIAN跟多字节类型的数据有关的比如int,short,long型&…

移植u-boot-2012.04.01到jz2440开发板

今天我给大家分享一下如何移植一个纯净的uboot到jz2440开发大版&#xff0c;通过记录学习分享&#xff0c;与大家一起进步&#xff01;&#xff01;&#xff01; 1.首先我们在uboot官网下载u-boot-2012.04.01.tar.bz2&#xff0c;建立source insight工程。将下载好的uboot通过…

温习了一下java线程状态方面的知识总结一

好长时间没有复习线程状态这块&#xff0c;读并发编程实战正好看着这块&#xff0c;顺便复习一下&#xff1a; 1.线程的五种状态&#xff1a; 2.线程五种状态的转换图&#xff1a; wait()会立刻释放synchronized(obj)中的锁以便其它线程可以执行obj.notify 但是notify() 不会立…

WinForm:进度条的实现(异步)

在WinForm中经常遇到一些费时的操作界面&#xff0c;比如统计某个磁盘分区的文件夹或者文件数目&#xff0c;如果分区很大或者文件过多的话&#xff0c;处理不好就会造成“假死”的情况&#xff0c;或者报“线程间操作无效”的异常&#xff0c;为了解决这个问题&#xff0c;可以…

移植u-boot-2012.04.01到jz2440开发板之修改代码支持NAND启动

上一篇文章我们已经修改了uboot源码使其能够正常打印输出了&#xff0c;但是输出停到了nand启动那里&#xff0c;所以这篇文章就来记录如何修改源码使uboot支持NAND启动。 原来的代码在链接时加了”-pie”选项, 使得u-boot.bin里多了”(.rel)”, “*(.dynsym)”使得程序非常大…