10.C++-构造函数初始化列表、类const成员、对象构造顺序、析构函数
首先回忆下,以前学的const
单独使用const修饰变量时,是定义的常量,比如:const int i=1;
使用volatile const修饰变量时,定义的是只读变量
使用const & 修饰变量时,定义的是只读变量
在类中是否可以定义const成员?
直接来写代码:
#include <stdio.h>
class Test
{
private:
const int ci;
public:
// Test()
// {
// ci=10;
// }
int getCI()
{
return ci;
}
};
int main()
{
Test t;
printf("%d\n",t.getCI());
return ;
}
编译出错:
test.cpp: In function ‘int main()’: test.cpp:: error: structure ‘t’ with uninitialized const members
从编译信息看出,由于结构体t的const成员没有初始化,所以执行printf()出错.
接下来取消上面示例的屏蔽,使用上章学习的构造函数来初始化const
编译还是出错:
test.cpp: In constructor ‘Test::Test()’: test.cpp:: error: uninitialized member ‘Test::ci’ with ‘const’ type ‘const int’ test.cpp:: error: assignment of read-only data-member ‘Test::ci’
从编译信息看出, Test::Test()构造函数里,不能直接初始化const变量.
所以,在C++中,便引入了构造函数初始化列表(除了可以给成员变量初始化,还可以对const成员初始化)
初始化列表位于构造函数名右侧,以一个冒号开始,接着便是需要初始化的变量,以逗号隔开,例如:
class Example
{
private:
int i;
float j;
const int ci;
int *p;
public:
Test(): j(1.5),i(),ci() //初始化i=2,j=1.5,ci=10
{
p=new int;
*p=;
}
};
注意:
-列表成员的初始化顺序只与成员的声明顺序相同,与初始化列表的位置无关
比如上个示例,初始化列表初始化的顺序为: i=2,j=1.5,ci=10
-调用构造函数初始化时,会先执行初始化列表,再执行构造函数里的内容.
那class类里的const成员是常量还是只读变量?
参考以下示例:
#include <stdio.h> class Test
{
private:
const int ci;
public:
Test():ci()
{ }
int getCI()
{
return ci;
}
void setCI(int val)
{
int *p=const_cast<int *>(&ci);
*p=val;
}
}; int main()
{
Test t;
t.setCI();
printf("%d\n",t.getCI());
return ;
}
编译运行:
所以class类里的const成员, 定义的是只读变量
对象的构造顺序
C++中的类可以定义多个对象,那么对象构造的顺序又是怎么样的?
对于局部对象(栈)
-程序执行到对象的定义语句时,便进行构造
对于通过new创建的对象(堆)
-和局部对象一样,程序执行到new语句时,便进行构造
对于全局对象(静态存储区)
-对象的构造顺序是不确定的,所以要尽量避免多个全局对象之间的相互依赖.
对象的销毁-析构函数
之前我们学习过创建对象时,有构造函数进行初始化.
同样的,对象被销毁前也应该要有一些清理工作,所以,C++中引入了一个特殊的清理函数-析构函数
- 析构函数的功能与构造函数相反,在对象被摧毁时自动调用
- 析构函数没有参数,也没有返回值类型声明
定义为: ~class_name(),例如:
class Test{
public:
Test(){ } //构造函数
~Test(){ } //析构函数
};
注意:
- 在类里,当定义了析构函数,编译器就不会提供默认的构造函数了,所以还要自己定义一个构造函数。
- 使用new创建的对象变量,在不使用时,需要使用delete,才能调用析构函数
参考以下示例:
#include <stdio.h> class Test
{
int val; public:
Test(int i)
{
val=i;
printf("Test() val=%d\n",val);
}
~Test()
{
printf("~Test() val=%d\n",val);
}
}; int main()
{
Test t1();
Test* t2 = new Test(); // delete t2;
return ;
}
编译运行:
Test()
Test()
~Test()
从打印结果可以看出,t2的析构函数没有打印,所以只打印了:~Test(1)
取消屏蔽后再次运行:
Test()
Test()
~Test()
~Test()
总结:
当类中有成员需要内存申请,文件打开,链接数据库等时,则需要定义析构函数,进行回收资源
(和拷贝构造函数类似)
10.C++-构造函数初始化列表、类const成员、对象构造顺序、析构函数的更多相关文章
- <四>构造函数初始化列表
示例代码1 点击查看代码 class CDate{ public: CDate(int _year,int _month, int _day){ this->year=_year; this-& ...
- 从零开始学C++之构造函数与析构函数(二):初始化列表(const和引用成员)、拷贝构造函数
一.构造函数初始化列表 推荐在构造函数初始化列表中进行初始化 构造函数的执行分为两个阶段 初始化段 普通计算段 (一).对象成员及其初始化 C++ Code 1 2 3 4 5 6 7 8 9 1 ...
- 初始化列表(const和引用成员)、拷贝构造函数
一.构造函数初始化列表 推荐在构造函数初始化列表中进行初始化 构造函数的执行分为两个阶段 初始化段 普通计算段 (一).对象成员及其初始化 C++ Code 1 2 3 4 5 6 7 8 9 1 ...
- const成员或者引用成员必须使用构造函数初始化列表的方式
#include<iostream.h> class A { const int a; int b; }; void main() { A obja; }编译出现如下错误:error C2 ...
- C++类构造函数初始化列表
C++类构造函数初始化列表 构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式.例如: class CExample {public: ...
- C++类构造函数初始化列表(转)
构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式.例如: { public: int a; float b; //构 ...
- C++中为什么构造函数初始化列表
已经有个构造函数负责初始化,为什么还需要构造函数初始化表呢? 在以下三种情况下需要使用初始化成员列表:一,需要初始化的数据成员是对象的情况:二,需要初始化const修饰的类成员:三,需要初始化引用成员 ...
- C++构造函数初始化列表与构造函数中的赋值的区别
C++类中成员变量的初始化有两种方式:构造函数初始化列表和构造函数体内赋值. 一.内部数据类型(char,int……指针等) class Animal { public: Animal(int wei ...
- C++:用成员初始化列表对数据成员初始化
1.在声明类时,对数据成员的初始化工作一般在构造函数中用赋值语句进行. 例如: class Complex{ private: double real; double imag; public: Co ...
随机推荐
- git-创建新项目
1.一般第一次使用git,需要进行全局设置,如果下次创建新项目或者fork别人的项目,则不需要再进行设置:但是如果想要提交到不同的代码管理网站,则需要再设置,比如现在我的是在gitlab.com上进行 ...
- 几种String对象方法的区别
1.在String对象方法中,发现.slice()方法和.substring()方法的作用几乎相同,都是根据起始索引返回截取得到的字符串.经过查阅资料和实测得到区别: 正常情况下索引都为正值,返回值为 ...
- 制作Visual Studio 2019 (VS 2019) 离线安装包
与制作Visual Studio 2017的离线安装包(https://www.cnblogs.com/danzhang/p/6534341.html)类似,可以使用--layout的参数在安装前先下 ...
- 使用TheFolderSpy监控文件夹的变化-邮件通知
一.概述 当我们的文档或者代码文件发布在公网.共享文件夹中,其他用户具备访问或修改的权限时,就存在文档被覆盖或删除的分享.另外一个典型的场景,发布在Web服务器上的网页文件,在网站版本不更新的时间,服 ...
- mac下安装安卓开发环境
对于做ios的人来说,安装安卓开发环境,最好是在mac下安装了,我的mac是10.8.2,64位系统的 安卓开发环境需要下面几个东西: 1 jdk(mac下已经默认有了,可以在命令提示符下输入java ...
- H5+.Net Webapi集成微信分享前后端代码 微信JS-SDK wx.onMenuShareTimeline wx.onMenuShareAppMessage
说明: 1/因为赚麻烦这里没有使用数据库或服务器缓存来存储access_token和jsapi_ticket,为了方便这里使用了本地的xml进行持久化这两个值以及这两个值的创建时间和有限期限. 2/每 ...
- CPU Hardwar
GPU负责把线程块分配到各个SM上处理. CUDA对申请的线程块何时运行,以及在哪个SM上运行是没有保证的.这恰好是GPU的优势,这种方式带来了灵活性,不需程序根据SM的数量去配置程序. 但是一个bl ...
- Jira/Confluence的备份、恢复和迁移
之前的文章已经分别详细介绍了Jira.Confluence的安装及二者账号对接的操作方法,下面简单说下二者的备份.恢复和迁移: 一.Jira.Confluence的备份.恢复1)Confluence的 ...
- 本地连接虚拟机 Oracle数据库 报ORA-12541:TNS:no listener
一.环境 本机环境:win10,pl/sql Developer 虚拟机环境:win10,oracle 11g 1.本机和虚拟机互相ping都可以ping通. 2.虚拟机监听程序已启动. 二.配置文件 ...
- Android精通教程-第一节Android入门简介
前言 大家好,给大家带来Android精通教程-第一节Android入门简介的概述,希望你们喜欢 每日一句 If life were predictable it would cease to be ...