一个类的成员变量如果是另一个类的对象,就称之为“成员对象”。包含成员对象的类叫封闭类(enclosed class)

成员对象的初始化
创建封闭类的对象时,它包含的成员对象也需要被创建,这就会引发成员对象构造函数的调用。如何让编译器知道,成员对象到底是用哪个构造函数初始化的呢?这就需要借助封闭类构造函数的初始化列表。

构造函数初始化列表的写法如下:
类名::构造函数名(参数表): 成员变量1(参数表), 成员变量2(参数表), …
{
//TODO:
}

对于基本类型的成员变量,“参数表”中只有一个值,就是初始值,在调用构造函数时,会把这个初始值直接赋给成员变量。

但是对于成员对象,“参数表”中存放的是构造函数的参数,它可能是一个值,也可能是多个值,它指明了该成员对象如何被初

#include <iostream>
using namespace std;//轮胎类
class Tyre{public:Tyre(int radius, int width);void show() const;
private:int m_radius;  //半径int m_width;  //宽度
};
Tyre::Tyre(int radius, int width) : m_radius(radius), m_width(width){ }
void Tyre::show() const {cout << "轮毂半径:" << this->m_radius << "吋" << endl;cout << "轮胎宽度:" << this->m_width << "mm" << endl;
}//引擎类
class Engine{public:Engine(float displacement = 2.0);void show() const;
private:float m_displacement;
};
Engine::Engine(float displacement) : m_displacement(displacement) {}
void Engine::show() const {cout << "排量:" << this->m_displacement << "L" << endl;
}//汽车类
class Car{public:Car(int price, int radius, int width);void show() const;
private:int m_price;  //价格Tyre m_tyre;Engine m_engine;
};
Car::Car(int price, int radius, int width): m_price(price), m_tyre(radius, width)/*指明m_tyre对象的初始化方式*/{ };
void Car::show() const {cout << "价格:" << this->m_price << "¥" << endl;this->m_tyre.show();this->m_engine.show();
}int main()
{Car car(200000, 19, 245);car.show();return 0;
}

Car 是一个封闭类,它有两个成员对象:m_tyre 和 m_engine。在编译第 51 行时,编译器需要知道 car 对象中的 m_tyre 和 m_engine 成员对象该如何初始化。

编评器已经知道这里的 car 对象是用第 42 行的 Car(int price, int radius, int width) 构造函数初始化的,那么 m_tyre 和 m_engine 该如何初始化,就要看第 42 行后面的初始化列表了。该初始化列表表明:
m_tyre 应以 radius 和 width 作为参数调用 Tyre(int radius, int width) 构造函数初始化。
但是这里并没有说明 m_engine 该如何处理。在这种情况下,编译器就认为 m_engine 应该用 Engine 类的无参构造函数初始化。而 Engine 类确实有一个无参构造函数(因为设置了默认参数),因此,整个 car 对象的初始化问题就都解决了。

总之,生成封闭类对象的语句一定要让编译器能够弄明白其成员对象是如何初始化的,否则就会编译错误。

在上面的程序中,如果 Car 类的构造函数没有初始化列表,那么第 51 行就会编译出错,因为编译器不知道该如何初始化 car.m_tyre 对象,因为 Tyre 类没有无参构造函数,而编译器又找不到用来初始化 car.m_tyre 对象的参数。

成员对象的消亡

封闭类对象生成时,先执行所有成员对象的构造函数,然后才执行封闭类自己的构造函数。成员对象构造函数的执行次序和成员对象在类定义中的次序一致,与它们在构造函数初始化列表中出现的次序无关。

当封闭类对象消亡时,先执行封闭类的析构函数,然后再执行成员对象的析构函数,成员对象析构函数的执行次序和构造函数的执行次序相反,即先构造的后析构,这是 C++ 处理此类次序问题的一般规律。

请看下面的代码:

#include<iostream>
using namespace std;
class Tyre {public:Tyre() { cout << "Tyre constructor" << endl; }~Tyre() { cout << "Tyre destructor" << endl; }
};
class Engine {public:Engine() { cout << "Engine constructor" << endl; }~Engine() { cout << "Engine destructor" << endl; }
};
class Car {private:Engine engine;Tyre tyre;
public:Car() { cout << "Car constructor" << endl; }~Car() { cout << "Car destructor" << endl; }
};
int main() {Car car;return 0;
}

C++成员对象和封闭类相关推荐

  1. [FxCop.设计规则]16. 不要在封闭类中声明虚成员

    16.     不要在封闭类中声明虚成员 翻译概述: 一条比较无聊的规则,并且VB.NET和C#编译器都已经内嵌的禁止代码违反这条规则. 引起的原因: 一个公共的封闭类型中包含虚成员.这条规则不检查d ...

  2. kotlin学习笔记——枚举、封闭类

    1.枚举 kotlin中提供类枚举的实现,与java相同.枚举可以带参数,如 enum Icon(val res: Int){MENU(R.drawable.menu),BACK(R.drawable ...

  3. matlab emf 读取,20140219-Emf_Demo EMF 矢量图 可以读取和保存EMF 的封闭类 非常实用 matlab 238万源代码下载- www.pudn.com...

    文件名称: 20140219-Emf_Demo下载 收藏√  [ 5  4  3  2  1 ] 开发工具: Visual C++ 文件大小: 6312 KB 上传时间: 2014-07-10 下载次 ...

  4. 转向Kotlin——数据类和封闭类

    数据类和封闭类是Kotlin中的两种特殊的类,今天一起了解一下.更多精彩内容也可以关注我的微信公众号--Android机动车 数据类 数据类是Kotlin的一个语法糖.Kotlin编译器会自动为数据类 ...

  5. Kt学习笔记(九)数据类、封闭类

    文章目录 一.数据类 1.1.使用数据类 1.2.对象复制 1.3.数据类成员的解构 二.封闭类 一.数据类   数据类是 Kotlin 的一个语法糖. Kotlin 编译器会自动为数据类生成一些成员 ...

  6. C#封闭方法和封闭类:sealed

    C#中的封闭方法和封闭类 一.封闭类 使用sealed修饰符修饰的类为封闭类,表示该类不可被继承.故,该修饰符不可与abstract一起使用,因为抽象类的方法需要继承的实体类做具体实现,必须被继承才有 ...

  7. 封闭类(Sealed Classes)

    封闭类(Sealed Classes)用于代表严格的类结构,值只能是有限集合中的某中类型,不可以是任何其 它类型.这就相当于一个枚举类的扩展:枚举值集合的类型是严格限制的,但每个 枚举常量只有一个实例 ...

  8. java 不是封闭类_java – 不是一个封闭的类错误Android Studio

    我在 Android开发中是新的,并没有深入的Java知识.我长时间困扰着一个问题.我试图在按钮点击上打开一个新的活动.但是我收到一个错误:错误:不是封闭类:Katra_home. 这是MainAct ...

  9. java 不是封闭类_java – MainActivity.this不是一个封闭的类AsyncTask

    我试图第一次创建一个AsyncTask,但我没有太多的运气. 我的AsyncTask需要从服务器获取一些信息,然后将新的布局添加到主布局以显示此信息. 一切似乎或多或少是清楚的,但是错误信息" ...

最新文章

  1. python随机选取列表中的一个字符串_如何从Python中的列表中选择随机字符串?
  2. 我的python之路(四):列表
  3. Java ArrayList和Vector、LinkedList与ArrayList、数组(Array)和列表集合(ArrayList)的区别...
  4. 看动画学算法之:排序-归并排序
  5. Python程序开发——第一章 基本python语法
  6. 基于php的地铁查询系统,HTML5 Canvas实现交互式地铁线路图
  7. cefsharp49显示html,CefSharp-cefshar
  8. 马上有钱:揭密25种成为有钱人的方法(图)
  9. MySQL sleep函数使用详解
  10. WinDbg分析dump文件排查bug
  11. idea创建Maven项目后启动报404
  12. java设置打印字体大小_PHP调整字体大小打印到网络热敏打印机
  13. 屏幕录像软件Community Clips Recorder简介及其使用技巧(郝宪玮)
  14. 720云VR全景支持入驻高德地图,打造新一代沉浸式文旅消费体验
  15. java中boot是什么,Spring boot是什么
  16. unity2D横版游戏教程-3 Cinemachine镜头移动
  17. python计算利息程序_Python——GUI编程 利息计算器 作业9(python programming)-Go语言中文社区...
  18. 【AcWing 165】 小猫爬山 简单dfs + 剪枝优化
  19. 安装SQLServer2019
  20. android百度人脸采集免费,Android 调用百度人脸采集

热门文章

  1. 基于 Module 的 Laravel API 架构
  2. 彻底搞懂JavaScript执行机制
  3. 11.18-11.19总结(transform,transition,媒体查询,弹性盒子)
  4. jsp+urlrewrite实现html分页简单粗暴实现
  5. phpstorm8 license key
  6. 【RHCA翻译计划】EX436第一章:集群存储概论2
  7. 从零开始学习OpenGL ES之五 – 材质
  8. Android:理想的框架开发母板——高焕堂
  9. BLE Mesh(1)—— 简述
  10. 李永乐线性代数手写笔记-特征值和特征向量