C++ 构造过程和析构过程
1、C++构造和析构的过程,类似于穿衣脱衣的过程。穿衣是:先穿内衣,再穿外套。脱衣是:先脱外套,再脱内衣。C++构造过程:首先调用父类构造方法,再调用子类构造方法。C++析构过程:首先调用子类析构方法,再调用父类析构方法。
2、子类不能继承父类的构造方法和析构方法,除此之外,其他的成员都能继承,包括父类的private成员,只不过子类不能访问private成员。
3、思考一下,为什么子类不能继承父类的构造方法?
想一想,构造方法是干什么的?构造方法是初始化对象的成分,创建对象。从语义上讲,父类构造方法初始化父类成分,构造父类对象。子类构造方法在父类对象的基础上,初始化子类专有成分,构造子类对象。如果子类继承父类构造方法,那么子类暴露一个接口,返回父类对象,这显然不合理。因此,子类不能继承父类的构造方法。
4、父类的成分只能在父类构造方法中初始化,子类只能初始化自己的专有成分,不能初始化父类的成分,可以在方法内赋值。子类如果初始化父类成分,编译报错:非法的成员初始化,不是基或成员。那么问题来了,子类没有继承父类的构造方法,那么子类如何初始化父类的成分呢?
5、子类不能继承父类的构造方法,但是可以调用父类的构造方法,而且必须调用父类的构造方法,确保父类成分初始化。如果没有显示调用父类的构造方法,会隐式调用父类的default构造方法。子类没有显式调用父类构造方法,父类没有提供default构造方法,编译报错:没有合适的default构造方法可用。
6、构造过程可认为:父类成员初始化列表,父类构造方法内赋值,子类成员初始化列表,子类构造方法内赋值。
7、C++析构方法能不能被继承,是有争议的。个人认为不能继承。有人说,不能继承,为什么子类可以调用。从语义上讲,为什么设计析构方法,析构方法撤销对象的成分。父类析构方法撤销父类的成分,子类构造方法撤销子类专有的成分。
8、析构方法是一种特殊的方法。主要体现在:
a、子类可以显式调用父类的析构方法;
b、子类不能隐藏父类的析构方法;
c、析构方法的重写规则不同,一般的virtual成员方法,重写要求方法名必须相同。析构方法的重写,方法名不同,分别是父类名和子类名。同时,纯虚的成员方法要求子类必须重写,父类可以不实现。纯虚的析构方法也要求子类必须重写(用户不重写,编译器会生成一个重写的析构方法),同时父类必须提供实现,因为必定要调用父类的析构方法。
9、子类构造方法必须调用父类构造方法,与此类似,子类析构方法执行完,必定调用父类的析构方法,可以认为子类析构方法执行完,创建一个对父类析构方法的调用。即使子类析构方法重写了父类的析构方法,子类析构方法执行完,还是要调用父类的析构方法。
10、那么问题来了,不管有没有重写,子类析构方法执行完,都必定要调用父类的析构方法。那么重写析构方法还有什么意义呢?
考虑,指针指向子类,指针的表面类型是父类,delete指针。如果没有重写析构方法,那么delete动作直接调用父类的析构方法,而不是先调用子类的析构方法,再调用父类的析构方法。
11、对象的析构过程可认为:第一步,子类析构方法撤销专有的成分,对于类类型,递归调用析构方法,对于内置类型不需要做什么,可认为不再使用它占用的内存;第二步,调用父类的析构方法,对于类类型,递归调用析构方法,对于内置类型,不需要做什么事,可认为不再使用它占用的内存。
12、什么时候声明析构方法为virtual呢?
当类中有virtual方法时,应该是声明析构方法为virtual,为什么?类中有virtual方法,意味着面向抽象编程,就会有父类指针指向子类对象。这种情况下,为了保证delete父类指针的时候,先调用子类析构方法(撤销子类专有成分),再调用父类析构方法(撤销父类成分),必须将父类析构方法声明为virtual。
如果类中没有virtual方法,不要声明virtual析构方法,为啥?对于virtual,编译器做了一些幕后工作,导致对象变大。
C++ 构造过程和析构过程的更多相关文章
- 【09】绝不在构造和析构过程中调用virtual方法
1.绝不在构造和析构过程中调用virtual方法,为啥? 原因很简单,对于前者,这种情况下,子类专有成分还没有构造,对于后者,子类专有成分已经销毁,因此调用的并不是子类重写的方法,这不是程序员所期望的 ...
- Effective C++ .09 不在构造和析构过程中调用virtual函数
看过C++对象模型的话就可以知道,在构造基类时,完整的vtable没有建立起来(表项没有被相应的子类函数替换),因而无法调用到子类的函数(即构造函数中的virtual函数是本类里的方法,不是virtu ...
- Swift的构造和析构过程
构造过程 Swift的构造过程通过定义构造器来实现. 只是与Objective-C不同的是,Swift的构造器不须要返回值,相同也不须要表明Func. 另外值得提的是,当构造器中为存储型属性赋值时.不 ...
- Swift2.1 语法指南——析构过程
原档:https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programmi ...
- swift学习笔记之-析构过程
//析构过程deist import UIKit /*析构过程(Deinitialization):析构器只适用于类类型,当一个类的实例被释放之前,析构器会被立即调用.析构器用关键字deinit来标示 ...
- 学习Swift -- 析构过程
析构过程 析构器只适用于类类型,当一个类的实例被释放之前,析构器会被立即调用.析构器用关键字deinit来标示,类似于构造器要用init来标示. 原理 Swift 会自动释放不再需要的实例以释放资源, ...
- Swift 析构过程
在一个类的实例被释放之前,析构函数被立即调用.用关键字deinit来标示析构函数,类似于初始化函数用init来标示.析构函数只适用于类类型. 析构过程原理 Swift 会自动释放不再需要的实例以释放资 ...
- php 启动过程 - reqeust RINIT 过程
php 启动过程 - reqeust RINIT 过程 概述 apache 接收到请求之后, 交给 php 处理 php 模块在接收到请求后, 会对请求进行初始化, 及 RINIT 过程 调用触发 a ...
- VScript 函数调用的两种分类:Sub过程和Function过程
来源:http://soft.zdnet.com.cn/software_zone/2007/0925/523318.shtml 在 VBScript 中,过程被分为两类:Sub 过程和 Functi ...
随机推荐
- C语言字符串查找函数
#include <string.h> #include <stdio.h> char * string_search(char long_str[], char short_ ...
- Android开发之Bitmap.Config.RGB_565
在学习xutils框架的时候,看到sample代码中有一行这样的代码: bitmapUtils.configDefaultBitmapConfig(Bitmap.Config.RGB_565); Bi ...
- wifi mode: AP,Client,Ad-hoc,802.11s,Pseudo Ad-hoc(ahdemo),Monitor,AP(WDS),Client(WDS)
openwrt wifi mode:APClientAd-hoc802.11sPseudo Ad-hoc(ahdemo)MonitorAP(WDS)Client(WDS) http://forum.a ...
- 请问JDBC中IN语句怎么构建
用PreparedStatement 传多参数时,如果参数个数不确定,还想使用?参数避免sql注入,只有一个办法 根据传递的参数个数,拼接sql语句为 SELECT * FROM TABLE_A WH ...
- MYI 文件内容
参考 http://blog.itpub.net/703656/viewspace-1018470/ 创建表结构 create table test(name char(20), age int, c ...
- OK335xS davinci mdio driver hacking
/******************************************************************************* * OK335xS davinci m ...
- Sharepoint网站创建自定义导航全记录
转:http://tech.it168.com/a2009/1207/820/000000820524_all.shtml [IT168 技术文档]在一个Sharepoint网站中可以创建子网站,页面 ...
- svc 报“由于扩展配置问题而无法提供您请求的页面。如果该页面是脚本,请添加处理程序。如果应下载文件,请添加 MIME 映射。“的HTTP 错误 404.3 – Not Found
原因:系统没有默认为IIS注册WCF服务的svc文件的MIME映射. 解决方法:管理员身份运行C:\Windows\Microsoft.NET\Framework\v3.0\Windows Commu ...
- MySQL中间层 Atlas
Atlas是由 Qihoo 360, Web平台部基础架构团队开发维护的一个基于MySQL协议的数据中间层项目.它在MySQL官方推出的MySQL-Proxy 0.8.2版本的基础上,修改了大量bu ...
- ORACLE的sign函数和DECODE函数
比较大小函数 sign 函数语法:sign(n) 函数说明:取数字n的符号,大于0返回1,小于0返回-1,等于0返回0 示例:一.select sign( 100 ),sign(- 100 ),sig ...