首先回忆下,以前学的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. <四>构造函数初始化列表

    示例代码1 点击查看代码 class CDate{ public: CDate(int _year,int _month, int _day){ this->year=_year; this-& ...

  2. 从零开始学C++之构造函数与析构函数(二):初始化列表(const和引用成员)、拷贝构造函数

    一.构造函数初始化列表 推荐在构造函数初始化列表中进行初始化 构造函数的执行分为两个阶段 初始化段 普通计算段 (一).对象成员及其初始化  C++ Code  1 2 3 4 5 6 7 8 9 1 ...

  3. 初始化列表(const和引用成员)、拷贝构造函数

    一.构造函数初始化列表 推荐在构造函数初始化列表中进行初始化 构造函数的执行分为两个阶段 初始化段 普通计算段 (一).对象成员及其初始化  C++ Code  1 2 3 4 5 6 7 8 9 1 ...

  4. const成员或者引用成员必须使用构造函数初始化列表的方式

    #include<iostream.h> class A { const int a; int b; }; void main() { A obja; }编译出现如下错误:error C2 ...

  5. C++类构造函数初始化列表

    C++类构造函数初始化列表 构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式.例如: class CExample {public:     ...

  6. C++类构造函数初始化列表(转)

    构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式.例如: { public:     int a;     float b;     //构 ...

  7. C++中为什么构造函数初始化列表

    已经有个构造函数负责初始化,为什么还需要构造函数初始化表呢? 在以下三种情况下需要使用初始化成员列表:一,需要初始化的数据成员是对象的情况:二,需要初始化const修饰的类成员:三,需要初始化引用成员 ...

  8. C++构造函数初始化列表与构造函数中的赋值的区别

    C++类中成员变量的初始化有两种方式:构造函数初始化列表和构造函数体内赋值. 一.内部数据类型(char,int……指针等) class Animal { public: Animal(int wei ...

  9. C++:用成员初始化列表对数据成员初始化

    1.在声明类时,对数据成员的初始化工作一般在构造函数中用赋值语句进行. 例如: class Complex{ private: double real; double imag; public: Co ...

随机推荐

  1. s5 Docker的持久化存储和数据共享

    数据库容器的数据如何才能不会丢失?Docker的持久化存储技术.Docker的数据共享技术能极大提高开发人员的开发效率,边写代码,边看运行结果. 数据持久化之Data Volume Docker持久化 ...

  2. Shell脚本学习-echo命令

    跟着RUNOOB网站的教程学习的笔记 shell的echo指令与PHP的echo指令类似,都是用于字符串的输出.命令格式: echo string 1 显示普通字符串 echo "It is ...

  3. ASP.NET对大文件上传的解决方案

    在ASP.NET 开发的过程中,最大的问题就在于上传大文件时让开发者尤为的头疼,而且,上传时无法方便的做到多线程的操控和上传进度的显示.笔者在此给大家推荐一款简单易用的上传组件,从而快速便捷得解决了 ...

  4. winSocket编程(十)完成端口

    //本篇为转贴 本系列里完成端口的代码在两年前就已经写好了,但是由于许久没有写东西了,不知该如何提笔,所以这篇文档总是在酝酿之中……酝酿了两年之后,终于决定开始动笔了,但愿还不算晚….. 这篇文档我非 ...

  5. 前端之html表单

    html表单 用于搜集不同类型的用户输入 表单由不同类型的标签组成   1.<form>标签 定义整体的表单区域     * action属性 定义表单数据提交地址     * metho ...

  6. 题解 luogu P1144 【最短路计数】

    本蒟蒻也来发一次题解第一篇请见谅 这个题有几个要点 1.无向无权图,建图的时候别忘记建来回的有向边[因此WA掉1次 2.无权嘛,那么边长建成1就好了2333333 3.最短路采用迪杰斯特拉(别忘用堆优 ...

  7. Internetworking

    1 Introduction 所谓的InternetWorking就是将很多网络连接起来,那么在这种连接的网络下我们该如何传送封包呢? 2 IP and Routers 1 IP Datagram H ...

  8. 《深入理解JAVA虚拟机》——学习笔记

    JVM内存模型以及分区 JVM内存分为: 1.方法区:线程共享的区域,存储已经被虚拟机加载的类信息.常量.静态变量.即时编译器编译后的代码等数据 2.堆:线程共享的区域,存储对象实例,以及给数组分配的 ...

  9. 剑指offer编程题Java实现——面试题8旋转数组的最小数字

    剑指offer面试题8:旋转数组的最小数字 题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个递增排序数组的一个旋转,输出旋转数组的最小元素. 例如数组{3,4,5,1, ...

  10. windows快速打开命令窗口方式[利刃篇]

    windows当然是窗口界面操作了,谁有事没事去用什么命令行啊,但是当你要用的时候,也要会用才行哦. 打开命令行的方式小说一下: 1.开始 > 运行 > cmd , enter,  ok ...