C++ 初始化形式、变量初始化规则、类构造函数的初始化列表
来源:互联网 发布:java技术栈 编辑:程序博客网 时间:2024/06/05 12:49
类构造函数的初始化列表,举例
一个对象的构造分两部分,首先是分配空间,然后初始化。
只要有对象生成,不管是以什么形式生成,都会调用构造函数进行初始化。
然后下面有个例子,在蓝色区域Big类的复制构造函数中,使用初始化列表进行成员的初始化(方法1)没有问题,而如果不使用初始化列表、直接在函数里用里面注释掉的代码(方法2)则会报错:Base类没有合适的构造函数。
// W3-课程作业2-4.cpp : Defines the entry point for the console application.#include "stdafx.h"//下面程序的输出结果是://5, 5//5, 5//请填空:#include <iostream>using namespace std;class Base {public:int k;Base(int n) :k(n) { }};class Big {public:int v; Base b;// 在此处补充你的代码//Big ________________{}//Big ________________{}Big(int n) :v(n), b(n) {}<span style="color:#3333ff;">Big(const Big& a) :v(a.v), b(a.b){//v = a.v;//b = a.b;}</span>};int _tmain(int argc, _TCHAR* argv[]){Big a1(5); Big a2 = a1;cout << a1.v << "," << a1.b.k << endl;cout << a2.v << "," << a2.b.k << endl;system("pause");return 0;}错误的原因如下。
构造一个对象时,先要构造这个对象的每一个属性,然后再执行该对象构造函数内部的语句。
初始化列表,其实是定义了如何构造每个属性。而初始化列表中没有列出的属性值,则是按照默认的方法初始化。
因此,对于这个例子而言:
方法1使用初始化列表:采用初始化列表中的b(a.b)构造Base类对象b,即调用了合成的复制构造函数,没有问题;
方法2不使用初始化列表:由于b的构造方法并没有在初始化列表中说明,因此在执行构造函数之前,需要先调用无参构造函数产生一个Base对象b,而这个无参构造函数并不存在,从而产生错误。
另外,之前以为方法2那样,执行b=a.b;时会调用合成的复制构造函数(即使是这样,b也还是没有合适的构造函数初始化。这条语句的时候已经是赋值,而不是初始化),事实上这句是赋值,调用的当然不是复制构造函数,而是执行合成赋值操作符(与合成复制构造函数类似)。这里把概念弄清楚,以后会少犯混的。
事实上,调用复制构造函数有三种情形:(而且复制构造函数本身是构造函数的一种,用来对对象初始化)
- 定义一个新对象,并用一个同类型的对象对它进行初始化时(显示使用复制构造函数)
- 当将该类型的对象传递给函数,即给形参初始化(隐式使用复制构造函数)
- 当从函数返回该类型的对象时,即给返回值对象初始化(隐式使用复制构造函数)
- (另)初始化顺序容器中的元素
- (另)根据元素初始化式列表初始化数组元素
派生类对象生成时,要先调用基类的构造函数。有两种方式调用:
- 显示方式。即在初始化列表中,指明 成员基类对象(基类对象) 这样的方式调用基类的构造函数
- 隐式方式。即不指明,自动得调用基类的默认构造函数。(你要确保基类有默认构造函数,否则出错)
初始化列表
必须对任何 const 或引用类型成员、以及没有默认构造函数的类类型的成员使用初始化列表。
(记住,可以初始化const对象或引用类型的对象,但不能对它们赋值。在开始执行构造函数的函数体之前,要完成初始化。
初始化const或引用类型数据成员的唯一机会是在构造函数初始化列表中。)
成员初始化的次序
成员被初始化的次序就是声明成员的次序。与构造函数初始化列表无关。(消亡顺序和声明顺序相反,忘了哪看的了。)
这是因为,后声明的变量有可能依赖先声明的成员变量,因此要有先声明先初始化,后声明的后初始化。参考此
C++ 支持两种形式的初始化
- 复制初始化。用等号。
- 直接初始化。把初始化式放在括号中。
当用于类类型对象时,初始化的复制形式和直接形式有所不同。直接初始化直接调用与实参匹配的构造函数,复制初始化总是调用复制构造函数。复制初始化首先使用指定构造函数创建一个临时对象,然后用复制构造函数将那个临时对象复制到正在创建的对象。所以,直接初始化效率高些。
变量初始化规则
- 内置类型变量的初始化
- 类类型变量的初始化
C++ 区分了声明和定义
定义,用于为变量分配存储空间,还可以为变量指定初始值。变量有且仅有一次定义。
声明,用于向程序表明变量的类型和名字(标识符)。变量可以声明多次。
定义也是声明,当定义变量时我们声明了它的类型和名字。
可以通过使用extern关键字声明变量而不定义它。extern声明不是定义,也不分配存储空间,它只是说明变量定义在程序的其他地方(文件)。
只有当声明也是定义时,声明才可以有初始化式,因为只有定义才分配存储空间。初始化式必须要有存储空间来进行初始化。如果声明有初始化式,那么它可被当作是定义,即使声明标记为extern。
且只有当extern声明位于函数外部时,才可以含有初始化式。
- C++ 初始化形式、变量初始化规则、类构造函数的初始化列表
- 【C/C++】构造函数的初始化列表
- C/C++ 通过初始化列表和构造函数内赋值初始化成员变量的区别
- C/C++ 通过初始化列表和构造函数内赋值初始化成员变量的区别
- C/C++ 通过初始化列表和构造函数内赋值初始化成员变量的区别
- C/C++ 通过初始化列表和构造函数内赋值初始化成员变量的区别
- C/C++ 通过初始化列表和构造函数内赋值初始化成员变量的区别
- C/C++ 通过初始化列表和构造函数内赋值初始化成员变量的区别
- C/C++ 通过初始化列表和构造函数内赋值初始化成员变量的区别
- C/C++ 通过初始化列表和构造函数内赋值初始化成员变量的区别
- 类的成员变量 声明顺序 决定 初始化顺序(构造函数初始化列表不影响)
- C++类构造函数初始化列表及初始化成员变量的误区
- 构造函数的初始化列表
- 构造函数的初始化列表
- 构造函数的初始化列表
- 构造函数的初始化列表
- 构造函数的初始化列表
- 构造函数的初始化列表
- html相关文章
- Service(一)简介
- poj 1436 Horizontally Visible Segments(线段树基础,区间染色,拆点)
- tmux
- [BZOJ 2436][NOI 2011]NOI嘉年华(DP优化)
- C++ 初始化形式、变量初始化规则、类构造函数的初始化列表
- Android使用DrawerLayout创建左右两个抽屉菜单
- 直接拿来用!最火的Android开源项目(二)
- Win8总提示安装FLASH插件怎么办?
- poj1664 放苹果
- 2015笔试上机题--求员工就餐最大享受度
- 直接拿来用!最火的Android开源项目(三)
- Android Studio中NDK开发(一)如何使用预编译好的.so动态链接库
- android开发备忘录