C++中的类——构造函数

2023-11-10

一、什么是构造函数

每个类都分别定义了它的对象被初始化的方式,类通过一个或几个特殊的成员函数来控制其对象的初始化过程,这些函数叫构造函数。构造函数的任务是初始化类对象的数据成员,无论何时只要类的对象被创建,就会执行构造函数。


二、构造函数的定义

class 类名

{

   访问说明符:

   类名(形参列表):初始值列表{函数体定义}

};

————————————————————————————————————————————————

1、构造函数的名字和类名相同、无返回类型有一个(可能为空的)参数列表和一个(可能为空的)函数体。

2、类可以包含多个构造函数,和其他重载函数差不多,不同的构造函数之间必须在参数数量或参数类型上有所区别。

3、不同于其他成员函数,构造函数不能被声明成const的。当我们创建类的一个const对象时,直到构造函数完成初始化过程,对象才能真正取得其“常亮”属性。因此,构造函数在const对象的构造过程中可以向其写值。

4、与其他成员函数相同的是,构造函数在类外定义时也需要明确指出是哪个类。

5、通常情况下,我们将构造函数声明为public的,可以供外部调用。然而有时候我们会将构造函数声明为private或protected的:(1)如果类的作者不希望用户直接构造一个类对象,着只是希望用户构造这个类的子类,那么就可以将构造函数声明为protected,而将该类的子类声明为public。(2)如果将构造函数声明为private,那只有这个类的成员函数才能构造这个类的对象。

默认构造函数

6、默认构造函数:默认构造函数没有参数,即在实例化对象时不需要给定初始值,这时所调用的构造函数为默认构造函数。默认构造函数的初始化规则:(1)如果存在类内初始值,则用它来初始化成员。(2)默认初始化。

7、合成的默认构造函数:当类没有声明任何构造函数时,编译器便会自动地生成默认构造函数。这个由编译器自动创建的构造函数叫做合成的默认构造函数。

8、如果类包含有内置类型或复合类型的成员,则只有当这些成员全部被赋予了类内的初始值时,这个类才适合于使用合成的默认构造函数。因为如果对象定义在块中,则该对象的成员初始值将是不可预测的。

9、有些时候编译器不能为某些类合成默认的构造函数。例如,如果类中包含一个其他类类型的成员且这个成员的类型没有默认构造函数,那么编译器将无法初始化该成员。对于这样的类来说,我们必须自定义默认构造函数,否则该类将没有可用的默认构造函数。当然还有一些其他的情况也会导致编译器无法生成一个正确的默认构造函数。

10、如果类内已经定义了其他的构造函数,那么强烈建议定义一个默认构造函数。我们定义默认构造函数的目的是因为我们即需要在定义类类型的对象时给予初始值的其他形式的构造函数,也需要在定义类类型的对象时不给予初始化参数而根据类内初始值初始化或默认初始化的默认构造函数。我们希望这个函数的作用完全等同于之前使用的合成默认构造函数。

11、在C++11新标准中,如果我们需要默认的行为,那么可以通过在参数列表后写上“=default”(不含引号)来要求编译器生成构造函数。其中,“=default”即可以和声明一起出现在类的内部,也可以作为定义出现在类的外部。在不支持C++11的情况下,可以用一个空参数列表空初始值列表(见下文)函数体内不对成员进行赋值操作的构造函数来代替(典型的:类名(){})。

构造函数初始值列表

构造函数初始值列表:类名(形参列表):数据成员1(初始值),数据成员2(初始值)...{函数体}

上面蓝色部分即为构造函数初始值列表,他负责为新创建的对象的一个或几个数据成员赋初始值。

————————————————————————————————————————————————

12、构造函数初始值是成员名字的一个列表,每个名字后紧跟括号括起来的(或者在花括号内)成员初始值。不同成员的初始化通过逗号分隔开来。

13、构造函数初始值列表只说明用于初始化成员的值,而不限定初始化的具体执行循序。实质上,成员的初始化顺序与它们在类定义中的出现顺序一致。然而如果一个成员是用另一个成员初始化的,那么这两个成员的初始化顺序就很重要了。有的编译器会当构造函数的初始值列表中的数据成员顺序与这些成员声明的顺序不符时生成一条警告信息。最好令构造函数初始值的顺序与成员声明的顺序保持一致,并且可能的话,最好用构造函数的参数作为成员的初始值,而避免使用同一个对象的其他成员,这样就不必考虑成员的初始化顺序了。

14、如果没有在构造函数的初始值列表中显式的初始化成员,则该成员将在构造函数体之前执行类内初始值初始化或默认初始化。这一点也就解释了在不支持C++11的情况下如何生成一个执行默认操作的默认构造函数(见第11点)。

15、一旦构造函数体开始执行,也就意味着初始化结束了。可以在构造函数体内部重新为成员赋值。有时我们可以忽略数据成员初始化和赋值之间的差异,但并非总能这样。例如,如果成员是const或者引用或属于某种类类型且该类没有定义默认构造函数时,必须将这个成员初始化。

默认实参构造函数

16、构造函数也可以具有默认的实参,如果一个构造函数为所有参数都提供了默认实参,则它实际上也定义了默认构造函数。

三、委托构造函数

class 类名

{

public:

   类名(int a,string b,vector<string> c):aa(a),bb(b){ cc=c; }//构造函数

   类名(形参列表):类名(0," "){}//委托构造函数

   类名(形参列表):类名(5,"hellol"){}//委托构造函数

private:

   int aa;

   string bb;

   vector<string> cc;

};

————————————————————————————————————————————————

17、C++11新标准扩展了构造函数初始值的功能,我们可以定义委托构造函数。一个委托构造函数使用它所属类的其他构造函数执行它自己的初始化过程,或者说它把它自己的一些(或者全部)职责委托给了其他构造函数。

18、委托构造函数也有一个成员初始值列表(相当于对构造函数的调用)和一个函数体。在委托构造函数内,成员初始值列表只有一个唯一的入口,就是类名本身。和其他成员初始值一样,类名后面紧跟圆括号括起来的参数列表,参数列表必须与另一个构造函数匹配。

19、当一个构造函数委托给另一个构造函数时,受委托的构造函数的初始值列表和函数体被依次执行,然后控制权才会交给委托者的函数体。

20、委托可以多级传递,即A可以委托给B,B又可以委托给C。

四、隐式的类类型转换

21、如果构造函数只接受一个实参,则它便具有了转换为此类类型的隐式转换机制。把这种构造函数称为转换构造函数。具体表现在:在成员函数的参数为类类型时,可以为其传一个数据成员值,该值会自动转换成一个类类型的临时对象作为实参。

22、需要注意以下几点;(1)转换前传递的实参必须具有对应的转换构造函数。(2)编译器只会自动的执行一步类型转换。(例如,需要一个string类型作为形参的转换构造函数,我们不能用一个字符串字面量作为实参去掉用需要该类类型作为形参的成员函数,因为这时需要两部转换)(3)临时的中间变量都是const,所有没有const的引用会失败。所以如果成员函数的形参为该类类型的引用,则必须将其定义为const类型。

#include <iostream>
using namespace std;

class part
{
public:
	part(string s):ss(s),ii(10){}
	part(int i,string s):ii(i),ss(s){}
	void foo(const part& partn){ss=partn.ss;}
	void print()
	{
		cout<<ii<<endl<<ss<<endl;
	}
private:
	int ii;
	string ss;
}part1(100,"world");

int main()
{
	part1.print();
	string s="hello";
	part1.foo(s);
	part1.print();
}

23、可以用explicit修饰构造函数从而达到如下效果(explicit只允许出现在类的内部):

   23.1、如果构造函数是转换构造函数,此时将无法进行隐式转换。

   23.2、发生隐式转换的另一种情况是,当我们执行拷贝形式的初始化时(=)。此时,只能使用直接初始化,而不能将explicit构造函数用于拷贝形式的初始化。

24、尽管编译器不会将explicit的构造函数用于隐式转换过程,但是可以显式的强制进行转换。

part1.foo(part("hellio"));

part1.foo(static_cast<part>"hello");

25、标准库中的构造函数

   25.1、接受一个单参数的const char*的string构造函数不是explicit的。

string s="hello";

string s("hello");

   25.2、接收一个容量参数的vector构造函数是explicit的。

vector<T> v(n);

五、聚合类

26、聚合类与C语言中的结构体很类似,它使得用户可以直接访问其成员,并且具有特殊的初始化语法形式。

27、当一个类满足如下条件时,我们说它是聚合类:

   27.1、所有成员都是public的

   27.2、没有定义任何构造函数

   27.3、没有类内初始值

   27.4、没有基类,也没有virtual函数。

28、可以用一个花括号括起来的成员初始值列表初始化聚合类的数据成员,初始值的顺序必须与声明的顺序一致。

29、如果初始值列表中的元素个数少于类的成员数量,则靠后的成员被值初始化。初始值列表的元素个数绝对不能超过类的成员数量。

六、字面值常量类

此部分可参考——C++11中的constexpr

30、数据成员都是字面值类型的聚合类是字面值常量类。

31、如果一个类不是聚合列,但它符合下述要求,则它也是一个字面值常量类。

   31.1、数据成员都必须是字面值类型

   31.2、类必须至少含有一个constexpr构造函数(尽管构造函数不能是const的)

   31.3、如果一个数据成员含有类内初始值,则内置类型成员的初始值必须是一条常量表达式;或者如果成员属于某种类类型,则初始值必须使用成员自己的constexpr构造函数

   31.4、类必须使用析构函数的默认定义,该成员负责销毁类的对象。

32、constexpr构造函数可以声明成=default的形式(或者是删除函数的形式)。否则,constexpr构造函数就必须既符合构造函数的要求(不能包含返回语句),又符合constexpr函数的要求(意味着它能拥有的唯一可执行语句就是返回语句)。综合这两点,constexpr构造函数体应该是空的。通过前置关键字constexpr就可以声明一个constexpr构造函数了。

33、constexpr构造函数必须初始化所以数据成员,初始值要么使用constexpr构造函数,要么是一条常量表达式。

34、constexpr构造函数用于生成constexpr对象以及constexpr函数的参数或返回类型。

#include <iostream>
using namespace std;
#include <string>

class part
{
public:
	constexpr part(int i, int s) :ii(i), ss(s) {}
	void print()
	{
		cout << ii << endl << ss << endl;
	}
	constexpr int poo()
	{
		return ss;
	}
private:
	int ii;
	int ss;
	//只能使用字面值类型
};

int main()
{
	constexpr part p1(10, 20);
	int data[p1.poo()];
	cout << sizeof(data) << endl;
}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++中的类——构造函数 的相关文章

  • Android项目JNI层C/C++文件中添加LOG信息

    第一步 在项目的mk文件中加入 LOCAL LDLIBS llog 第二步 在要添加LOG的cpp文件中引入一个头文件和添加一个定义 include
  • 【小宝解惑】VC++中delete和delete [] 的区别

    我们通常从教科书上看到这样的说明 delete 释放new分配的单个对象指针指向的内存 delete 释放new分配的对象数组指针指向的内存 那么 按照教科书的理解 我们看下下面的代码 int a new int 10 delete a 方
  • 类的私域变量访问方法

    类的私域变量只能在类的内部使用 类的实例对象不能访问 class JustCounter 类声明 secrectCount 0 私有变量 publicCount 0 公开变量 def count self 类方法 self secrectC
  • C++类的介绍

    最近在学习SLAM 顺便将C 类的知识复习一下 其中部分官方定义和程序设计方法来源于西北工业大学魏英老师 1 类的定义 是用户自定义的数据类型 C 一个类定义的形式如下 class 类名 成员列表 成员列表是类成员的集合 数目可以任意多 一
  • python学习日记【13 - 面向对象三】

    面向对象三 继承简介 方法重写 super 多重继承 多态 属性和方法 继承简介 继承是面向对象三大特性之一 通过继承我们可以使一个类获取到其他类中的属性和方法 在定义类时 可以在类名后面的括号中指定当前类的父类 超类 基类 继承提高了类的
  • python面向对象编程 类与实例 继承与多态 isinstance

    class Student object def init self name gender self name name self gender gender def set gender self gender if gender ma
  • 订单、支付、退款、发货、退货等编号自动生成类

    在商城网站中 订单编号的自动生成 ERP中各个单据的编号自动生成 都可以按照一下的方式来自动生成 第一步 定义常量订单编号前缀 订单编号起始数 订单编号步长 public static final String ORDER SN PREFI
  • C++ 实验五 NO.1 定义一个student类包含成员变量姓名,年龄,学号,用多文件组织类, 在student类中重载构造函数,用多种方式对该类的对象初始化

    文章目录 题目 main cpp student cpp student h course cpp course h 运行结果 题目 程序作者 冰糖 章 节 实验五 最后修改日期 2019年3月31日 题 目 实验目的 1 掌握类的定义 根
  • 【Python 3.7】餐馆:创建一个名为 Restaurant 的类,其方法 __init__() 设置两个属性:restaurant_name 和 cuisine_type 。

    Python 3 7 餐馆 创建一个名为 Restaurant 的类 其方法 init 设置两个属性 restaurant name 和 cuisine type 创建一个名为 describe restaurant 的方法和一个名为 op
  • leetcode 10. 正则表达式匹配

    2023 9 20 感觉是目前做过dp题里最难的一题了 本题首要的就是需要理解题意 翻了评论区我才发现之前一直理解的题意是错的 我原来理解的 匹配0次 是指 直接消失 不会影响到前面的字符 但是 和前一个字符其实是连体的 所以说 如果匹配0
  • 虚函数

    说一说虚函数 1 虚函数 就是在类的成员函数的前面加virtual关键字 2 虚函数通过虚函数表 虚表 来实现 虚表中存的是虚函数指针 3 虚函数和普通函数一样的 都是存在代码段的 只是他的指针又存到了虚表中 4 类的对象中存的是虚表指针
  • 构造函数调用顺序及初始化列表

    设有3个类A B C 其中A派生B B派生C 即 C gt B gt A 定义一个C对象 则 进入C对象的构造函数 检查C构造函数的初始化列表 看其中是否手动调用基类B构造函数 无论是否手动 都立即调用基类B构造函数 不同的是手动调用时 可
  • C++-- 如何在类外访问一个类中私有的成员变量?

    如何在类外访问一个类中私有的成员变量 我在网上搜答案的时候看到大部分回答都是在类内部创建一个接口 所以此方法我就不再多做赘述 今天我说的是利用指针 边看代码边理解 上代码 class Test private int a 10 int b
  • 类什么时候被加载 java

    创建对象实例时 new 创建子类对象实例 父类也被加载 使用类的静态成员时 静态属性 静态方法
  • C++ 抽象类

    抽象类 接口 接口描述了类的行为和功能 而无需完成类的特定实现 C 接口时通过抽象类实现的 设计抽象类的目的 是为了给其他类提供一个可以继承的适当的基类 抽象类本类不能被用于实例化对象 只能作为接口使用 注意 如果试图实例化一个抽象类的对象
  • 详解c++STL—容器deque

    目录 1 deque容器的基本概念 1 1 功能 1 2 deque与vector区别 1 3 deque内部工作原理 2 deque构造函数 2 1 功能描述 2 2 函数原型 2 3 示例 3 deque赋值操作 3 1 功能描述 3
  • java学习笔记——第八章 类和方法(二)

    8 4使用方法 java中的方法不能独立存在 他必须属于一个类或者一个对象 因此方法也不能像函数那样被独立执行 因此必须使用类或对象来调用 总结 方法不能独立定义 方法只能在类体中定义 逻辑上讲 方法要么属于该类本身 要么属于该类的一个对象
  • _thiscall调用约定的简单概念

    thiscall 我们知道在c中由三种调用约定 cdecl stdcall和 fastcall 其中 stdcall调用约定是windows平台的 在c 中还有一种约定 thiscall调用约定 它是一种类成员方法调用约定 当我们说起 th
  • ts中定义类、类的继承、修饰符

    首先 简单介绍ES6的class类 class Foo constructor name age 实例前的构造函数 实例添加name age属性 this name name this age age getName 原型添加getName
  • Lua和C++交互总结(很详细)

    出处 http blog csdn net shun fzll article details 39120965 一 lua堆栈 要理解lua和c 交互 首先要理解lua堆栈 简单来说 Lua和C c 语言通信的主要方法是一个无处不在的虚拟

随机推荐

  • 【运维工程师笔试试题】

    一 选择题 1 下列系统默认端口号错误的是 A SSH端口22 B mysql端口3306 C Telnet端口20 D Https端口443 2 linux系统中查看ip地址的命令是 A ipconig B ifconfig C icmp
  • java编写es搜索程序

    开发环境 java8 springboot pom文件导入依赖
  • 前端HTML网页之间传递数据多种办法,附代码案例

    先看效果 目前常用的有三种办法 session传递 cookie传递 url传递 url会暴露参数 其余的两个是保存在服务端和浏览器中 不会暴露在地址栏里面 使用url 下面依次介绍 一 session传递 index html h1 We
  • 微服务连接云端Sentinel 控制台失败及连接成功后出现链路空白问题(已解决)

    sentinel控制台服务器部署在云端 首先打算在本地启动微服务连接云上的sentinel 发现仅能注册进服务 却不能显示监控信息和链路信息 查询日志后发现 云上的sentinel只能从注册中心拿到微服务 但是还是没有真正的连上8179端口
  • CSS—— @keyframes 动画关键帧

    disc 动画名 可自定义 keyframes disc from transform rotate 0deg to transform rotate 360deg 说明 keyframes 1 from to 用于简单动画 只有起始和结束
  • 我是如何从不知道怎么写,到完成二十万字书稿的?

    一 去年过年的时候 父母从乡下来到我在洛阳的家 晚上陪他们看完新闻联播后 我忍不住激动的心情 特意把北航出版社给我签的书稿 Web全栈开发进阶之路 合同捧出来给他们看 并郑重其事地介绍了一番 我以为他们会大吃一惊 像孙权对吕蒙那样对我刮目相
  • 双层双向长短期记忆神经网络(bi-LSTM)的多输入时间序列回归预测——附代码

    目录 摘要 研究背景 滑动时间窗口的构建 双层双向长短期记忆神经网络构造 程序计算结果 本文Matlab代码分享 摘要 为了充分挖掘电力负荷与多维特征因素的非线性关系 提高负荷预测精度 提出了一种基于随机森林和双向长短期记忆 Bi LSTM
  • hp服务器显示完logo就黑屏,惠普电脑开机出现惠普标志后 便黑屏了是为什么

    惠普电脑开机出现惠普标志后黑屏的原因及解决办法 一 原因 1 内存条 显示器 显卡等硬件设备接触不良 2 电脑灰尘比较多使得散热不良致使CPU或显卡芯片温度过高而死机 3 恶意病毒入侵 破坏系统 4 系统文件损坏 二 解决办法 1 检查显示
  • 数据传输-零拷贝机制

    传统 IO 在开始谈零拷贝之前 首先要对传统的 IO 方式有一个概念 基于传统的 IO 方式 底层实际上通过调用read 和write 来实现 通过read 把数据从硬盘读取到内核缓冲区 再复制到用户缓冲区 然后再通过write 写入到so
  • Tensorflow新手通过PlayGround可视化初识神经网络

    北京 上海巡回站 NVIDIA DLI深度学习培训 2018年1月26 1月12日 NVIDIA 深度学习学院 带你快速进入火热的DL领域 阅读全文 gt
  • 【网络基础】通俗易懂的搞明白什么是IP地址(小白向)

    目录 前言 IP协议 IP地址 查看IP地址的方法 公有IP地址与私有IP地址 IP地址的分类 网络路由传输流程简化版 IP地址过去的分类 过去分类带来的问题 前言 由于博主是一个刚转行没多久的前端 所以本次的文章也是面向像我一样的小白 内
  • ADS1220调试

    最近在调试ADS1220已经调试成功 后续补全此文 有问题联系我qq625895734
  • 电子病历与HIS的区别以及发展前途

    电子病历与HIS的区别以及发展前途 袁永福 http www xdesigner cn 2006 12 16 以下是我个人观点 可能有不足或错误 基本介绍 医院信息管理系统 History Information System 简称HIS
  • SimpleFOC移植STM32(七)—— 移植STM32F405RGT6

    目录 说明 一 点亮LED 1 1 原理图 1 2 硬件准备 1 3 烧写 二 开环控制 2 1 硬件准备 2 2 硬件连接 2 3 打开工程 2 4 修改参数 2 5 编译下载 观察运行 三 角度读取 3 1 硬件准备 3 2 硬件连接
  • 概要设计文档编写规范

    原文链接 https blog csdn net nengyu article details 3758312 做软件到一定层次了 就要考虑到设计了 设计了很久 就是不系统 系统的设计需要一个记录 记录就用文档 那么对项目所有包括技术上的设
  • HTML5-长按事件

    div style width 100 div style width 90 height 200px background color CCC font size 48px 长按我 div div
  • OpenGL编程入门

    1 用Ubuntu开发OpenGL程序 http www linuxidc com Linux 2011 09 42146 htm 2 Ubuntu下搭建OpenGL开发环境 HelloWorld http eddiezh iteye co
  • 最近接触的技术汇集帖

    最近在网上查资料碰到好多没接触过的技术 先汇总在这里备用 以后慢慢吸收 1 JNA JNI的替代品 调用方式比JNI更直接 不再需要JNI那层中间接口 几乎达到Java直接调用动态库 2 SmallSQL 基于JDBC3 0转为Deskto
  • vue中动态修改style(修改伪元素样式),样式中使用data里面的数据

    需求 伪元素高度使用data中的变量 对其进行动态修改 实现 css less中使用变量的方式 声明css变量的时候 变量名前面要加两根连词线 变量名大小写敏感 header color和 Header Color是两个不同变量 var 函
  • C++中的类——构造函数

    一 什么是构造函数 每个类都分别定义了它的对象被初始化的方式 类通过一个或几个特殊的成员函数来控制其对象的初始化过程 这些函数叫构造函数 构造函数的任务是初始化类对象的数据成员 无论何时只要类的对象被创建 就会执行构造函数 二 构造函数的定