C++构造函数知识点整理(C++11标准)
引言
构造函数是c++中的一个比较难的语法知识点。编程实践中,由于在很多情况下可以不显示定义构造函数,或者,虽然定义构造函数的方式并不十分适当,但是程序也能正常运行,故而并不是特别引起开发者的重视。
实际上,构造函数对C++语言十分重要,深入理解构造函数既能加深对很多C++高级语法,尤其是编译时,运行时,类的实例化和继承等概念的理解,而且能帮助我们写出更加健壮的代码。
本文从C++构造函数的概念出发,研究构造函数相关的理论和应用。包括构造函数的分类、形式、编译、运行(调用)等。在叙述的同时,辅以一些程序例子,并在一些易混淆的地方与Java、C#的构造函数进行对比。
本文中一些知识点来源于一些专业著作和网上资源,文章结尾有对这些资源的引用。
构造函数的概念的语法形式
构造函数(constructor),是类的成员函数的一种(关于构造函数属不属于类的成员函数,这里不做深究。很多资料将构造函数称为构造子,尤其在Java和C#中,将构造函数称为constructor,而将类的其它函数称作方法 - method),其作用是在定义类的实例时执行初始化操作(例如类成员变量的初始化、赋值,以及一些其它的操作)。
我们知道,函数有三要素:函数名、形参列表和返回值。对于类成员函数来说,可能还包含其它修饰符,比如访问修饰符(public,protected,private),静态修饰符(static)等。而对于构造函数来说,跟普通的成员函数相比最大的不同如下:
1. 构造函数必须与类同名;
2. 构造函数没有返回值。
3. 构造函数不能被直接显示调用。构造函数会在实例化(instantiate)类的时候被运行时调用,但不能被程序员显示调用(也可以理解为,当在代码中创建一个类的实例时,就是在调用构造函数)。
例如:
class DemoClassA{
public:
DemoClassA(){}
DemoClassA(int a):m_a(a){
}
private:
int m_a;
};
上面的代码只是一个简单的例子,可以看到,定义了两个构造函数,其中一个时无参的默认构造函数,另外一个时重载(overloaded)的含参构造函数,并用构造函数初始化值列表对类的成员变量进行了初始化。
默认构造函数,合成默认构造函数
没有形参列表的构造函数称为默认构造函数。
开发者在定义一个类时,可以选择显示定一个构造函数(或者显示定义多个重载的构造函数),也可以不显示定义构造函数。如果开发者没有显示定义任何的构造函数(包括默认构造函数),则编译器会为类生成一个默认的构造函数,称为合成默认构造函数。
如果没有特殊需求,建议开发者显示定义默认构造函数(尤其在已经定义了非默认构造函数时),原因如下:
1. 很多情况下,创建一个类的实例时,调用程序并不急于(或者不能够)对类的成员变量进行有意义的初始化,而是在运行过程中通过类似Java的SetXXX或者C#的属性的方式对成员变量赋值,因而,保留类的默认构造函数,可以方便类的使用者在初始化时无需考虑成员变量的初始化问题。除非一个类在设计时,就明确要求在其实例化时通过构造函数获得一些参数值,以执行一些特定操作(比如成员变量赋值,逻辑判断等),此时应当定义非默认构造函数,并有意不定义默认构造函数,或者定义一个私有的默认构造函数,来达到禁止利用默认构造函数实例化的目的。
2. 当类的成员变量中包含基本数据类型或者复合数据类型(例如引用或者指针),这一点上,类成员变量的初始化规则跟函数局部变量的初始化规则相同。
构造函数的定义和重载
介绍构造函数的重载规则前,先简要梳理一下普通成员函数的重载和调用规则。
构造函数由于要初始化成员变量,故而不能被修饰成const成员函数。
构造函数初始值列表、类内初始值
类内初始值是指在定义成员变量时赋给成员的初始值,包括在成员变量声明之处给的初始值,或者在类外定义的初始值。
需要注意,在C++中,初始化和赋值是两个不同的概念。
构造函数的编译和运行
C++类的构造函数编译规则(参考对比Java和C#构造函数的编译和运行规则)
编译时,编译器知道一个类实例化时所需要的内存空间大小。
很多编译器能对成员变量进行优化,故而在c语言中定义一个结构体时需要注意的字节对齐问题,C++编译器能够帮助解决。
构造函数和析构函数
析构函数可以用virtual修饰,构造函数不能
参考资料
1. C++ Primer(中文版 第5版),Stanley B. Lippman,Josée Lajoie,Barbara E. Moo 著;王刚,杨巨峰 译;叶劲峰,李云,刘未鹏 等 校
2. http://blog.csdn.net/grief_of_the_nazgul/article/details/45741849
3.
C++构造函数知识点整理(C++11标准)的更多相关文章
- 合成的默认构造函数定义为delete的一种情况(针对C++11标准)
1. 默认初始化 如果定义变量时没有指定初值,则变量会被默认初始化,此时变量被赋予了"默认值". 对于类类型的变量来说,初始化都是依靠构造函数来完成的.因此,即使定义某个类的变量( ...
- JS知识点整理(二)
前言 这是对平时的一些读书笔记和理解进行整理的第二部分,第一部分请前往:JS知识点整理(一).本文包含一些易混淆.遗漏的知识点,也会配上一些例子,也许不是很完整,也许还会有点杂,但也许会有你需要的,后 ...
- C++ Primer中文版(第5版)(顶级畅销书重磅升级全面采用最新 C++ 11标准)
C++ Primer中文版(第5版)(顶级畅销书重磅升级全面采用最新 C++ 11标准) [美]Stanley B. Lippman( 斯坦利李普曼) Josee Lajoie(约瑟拉乔伊 ) B ...
- C++11标准之右值引用(rvalue reference)
1.右值引用引入的背景 临时对象的产生和拷贝所带来的效率折损,一直是C++所为人诟病的问题.但是C++标准允许编译器对于临时对象的产生具有完全的自由度,从而发展出了Copy Elision.RVO(包 ...
- 大数据 -- kafka学习笔记:知识点整理(部分转载)
一 为什么需要消息系统 1.解耦 允许你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束. 2.冗余 消息队列把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据丢失风险.许多 ...
- Python基础知识点整理(详细)
Python知识点整理(详细) 输出函数 print()可以向屏幕打印内容,或者在打开指定文件后,向文件中输入内容 输入函数 input([prompt])[prompt] 为输入的提示字符.该函数返 ...
- Flutter教程- Dart语言规范-知识点整理
Flutter教程- Dart语言知识点整理 Dart语言简介 Dart语言介绍 ① 注释的方式 ② 变量的声明 ③ 字符串的声明和使用 ④ 集合变量的声明 ⑤ 数字的处理 ⑥ 循环的格式 ⑦ 抛异常 ...
- vue前端面试题知识点整理
vue前端面试题知识点整理 1. 说一下Vue的双向绑定数据的原理 vue 实现数据双向绑定主要是:采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty() 来劫 ...
- CPP全面总结(涵盖C++11标准)
OOP之类和对象 1. this指针的引入 每个成员函数都有一个额外的隐含的形参,这个参数就是this指针,它指向调用对象的地址.默认情况下,this的类型是指向类类型非常量版本的常量指针.可以表示成 ...
随机推荐
- 报错:Cannot remove entries from nonexistent file c:\program files\anaconda3\lib\site-packages\easy-install.pth
Outline 这两天通过“掘金量化终端”跑模型策略,之前装好环境一直ok,可以顺畅的Running~ 下午重装了下 Anaconda,刚才跑的时候提示 缺少“gm”模块 (掘金量化必须包): 就按照 ...
- Kotlin开发Android笔记
外国人写的一个天气预报的例子,最后有源码下载地址,初学者可以研读一下 http://blog.csdn.net/true100/article/category/6257988 1:Kotlin介绍及 ...
- eclipse导入项目,项目名出现红叉的情况(修改版)
转至:http://blog.csdn.net/niu_hao/article/details/17440247 今天用eclipse导入同事发给我的一个项目之后,项目名称上面出现红叉,但是其他地方都 ...
- Linux一键安装web环境全攻略(阿里云ECS服务器)
摘自阿里云服务器官网,此处 一键安装包下载: 点此下载 安装须知 1.此安装包可在阿里云所有linux系统上部署安装,此安装包包含的软件及版本为: nginx:1.0.15.1.2.5.1.4.4 a ...
- ES6简单入门
let let命令用来声明块级作用域. 以前的JavaScript只有全局作用域和函数作用域, 没有块级作用域. // 示例1: if (1) { var a = "hello"; ...
- C# 事件浅析
前言 对于搞.net的朋友来说,经常会遇到关于事件和委托的问题:事件与委托有什么关系?事件的本质是什么?委托的本质又是什么?由于.net 做了大量的封装,对于初学者,这两个概念确实不怎么好理解.事件是 ...
- CodeMatic动软自动生成Nhibernate
前两天调查了下自动生成工具MyGeneration和codesmith前一个版本已经不更新了后面一个太高级生成 的代码包含了太多东西,没整明白.不过生成的xmlmapping很强大.所以干脆整合一下c ...
- html-2, a img ul li ol dl dt dd 标签与列表标签的简单使用
<!-- a: a{ /*清除a标签的下划线*/ text-decoration: none; } (1)超链接 href 超链接的地址 target: _self 默认 在当前中打开链接地 ...
- c语言单元测试框架--CuTest
1.简介 CuTest是一款微小的C语言单元测试框,是我迄今为止见到的最简洁的测试框架之一,只有2个文件,CuTest.c和CuTest.h,全部代码加起来不到一千行.麻雀虽小,五脏俱全,测试的构建. ...
- js自执行函数&扩展方法
我们通常将JS代码写在一个单独的JS文件中,然后在页面中引入该文件.但是,有时候引入后会碰到变量名或函数名与其它JS代码冲突的问题.那么如何解决这个问题呢?作用域隔离.在JS中,作用域是通过函数来划分 ...