【C++类和对象】类和对象(中):构造函数 {六个默认成员函数;构造函数的概念及特性;编译器自动生成的构造函数;默认构造函数}

news2024/11/23 23:10:08

一、类的六个默认成员函数

  • 如果一个类中什么成员都没有,简称为空类。
    空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员函数。

  • 默认成员函数:用户没有显式实现,编译器会自动生成的成员函数称为默认成员函数。
    在这里插入图片描述


二、构造函数

2.1 概念

日期类初始化函数的实现:

class Date
{
public:
	void Init(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}

	void Print()
	{
		cout <<_year<< "-" <<_month << "-"<< _day <<endl;
	}
private:
	int _year; // 年
	int _month; // 月
	int _day; // 日
};

int main()
{
	Date d1, d2;
	//通过调用成员函数进行初始化
    d1.Init(2022,1,11);
	d2.Init(2022, 1, 12);
	d1.Print();
	d2.Print();
	return 0;
}
  • 对于Date类,可以通过 Init 公有方法给对象初识化日期,但如果每次创建对象时都调用该方法设置信息,未免有点麻烦有时还可能忘记初始化,那能否在对象创建时,就将信息设置进去呢?

  • 构造函数是一个特殊的成员函数,名字与类名相同,定义对象时由编译器自动调用,以保证每个数据成员都有一个合适的初始值,并且在对象整个生命周期内只调用一次。


2.2 特性

  • 构造函数是特殊的成员函数(不能以普通函数的定义和调用规则去理解他),需要注意的是,构造函数虽然名称叫构造,但是构造函数的主要任务并不是开空间创建对象,而是初始化对象

其特征如下:

  1. 函数名与类名相同。

  2. 无返回值。(也不用写void)

  3. 对象实例化时编译器自动调用对应的构造函数。

  4. 对于对象中的自定义类型成员,编译器会自动调用其对应的默认构造函数。

  5. 构造函数可以重载。

  6. 构造函数的参数可以缺省。

为日期类实现构造函数:

class Date
{
public:
	// 1.无参构造函数
	Date()
	{}
    
	// 2.带参构造函数(与上一个函数可以构成重载)
	Date(int year, int month, int day)
	{
		_year = year;
	    _month = month;
		_day = day;
	}
    
    // 3.全缺省构造函数(三种默认构造函数只能同时存在一种)
	//Date(int year = 1, int month = 1, int day = 1)
	//{
	//	_year = year;
	//    _month = month;
	//	_day = day;
	//}
private:
	int _year;
	int _month;
	int _day;
};

void TestDate()
{
	Date d1; // 调用无参构造函数
	Date d2(2015, 1, 1); // 调用带参的构造函数
	// 注意:如果通过不用传参的构造函数创建对象时,对象后面不用跟括号,否则就成了函数声明
	// 以下代码的函数:声明了d3函数,该函数无参,返回一个日期类型的对象
	// Date d3();
}

注意:

  1. 如果通过默认构造函数不传参数创建对象时,对象后面不用跟括号,否则就成了函数声明
  2. 全缺省构造函数和无参构造函数不能同时存在,语法上能构成重载,但在调用时会产生歧义。

2.3 编译器自动生成的构造函数

如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成。

class Date
{
public:
	/*
	// 如果用户显式定义了构造函数,编译器将不再生成
	Date(int year, int month, int day)
	{
	_year = year;
	_month = month;
	_day = day;
	}
	*/
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	// 将Date类中构造函数屏蔽后,代码可以通过编译,因为编译器生成了一个无参的默认构造函数
	// 将Date类中构造函数放开,代码编译失败,因为一旦显式定义任何构造函数,编译器将不再生成
	// 无参构造函数,放开后报错:error C2512: “Date”: 没有合适的默认构造函数可用
	Date d1;
	return 0;
}

那么默认构造函数是如何初始化对象的呢?

C++把类型分成内置类型(基本类型)和自定义类型。

  • 内置类型:int/char/double/float/任意类型的指针 等语言自带的基本类型

  • 自定义类型:class/struct/union 等自己定义的类型

看看下面的程序,就会发现编译器生成默认的构造函数不会初始化内置类型的成员,但会调用自定义类型成员的默认构造函数。

class Time
{
public:
	//Time类型的默认构造函数
	Time()
	{
		cout << "Time()" << endl;
		_hour = 0;
		_minute = 0;
		_second = 0;
	}
private:
	int _hour;
	int _minute;
	int _second;
};

class Date
{
private:
	// 内置类型不做处理
	int _year;
	int _month;
	int _day;
	// 自定义类型会调用他的默认构造函数
	Time _t;
};

int main()
{
	Date d;
	return 0;
}

查漏补缺

  • 默认生成的构造函数不初始化内置类型,是C++早期设计的一个缺陷,其实内置类型也应该一并处理(初始化)。

  • C++11 中针对内置类型成员不初始化的缺陷,又打了补丁,即:内置类型成员变量在类中声明时可以给默认值。

    注意:这里不是初识化(是声明不是定义),而给默认值。

class Time
{
public:
Time()
{
cout << "Time()" << endl;
_hour = 0;
_minute = 0;
    _second = 0;
}
private:
int _hour;
int _minute;
int _second;
};
class Date
{
private:
// 内置类型可以给默认值(C++11的特性)
// 调用自动生成的构造函数时会将默认值赋给成员变量
int _year = 1970;
int _month = 1;
int _day = 1;
// 自定义类型会调用他的默认构造函数
Time _t;
};
int main()
{
Date d;
return 0;
}

2.4 默认构造函数

所谓默认构造函数其实就是不需传参就可以直接调用的构造函数:

  1. 没有显示定义构造函数,由编译器自动生成的构造函数。
  2. 显示定义的全缺省构造函数。
  3. 显示定义的无参构造函数。

提示:以上的三种默认构造函数只能同时存在一种。

全缺省和无参构造函数同时存在:

class Date
{
public:
Date()
{
_year = 1900;
_month = 1;
_day = 1;
}
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
// 以下测试函数能通过编译吗?
void Test()
{
Date d1;
}

测试结果:
在这里插入图片描述
编译报错:调用时会发生歧义

总结:

  1. 一般的类都会自己写构造函数。如显示定义一个全缺省构造函数,非常好用。
  2. 特殊情况才会采用默认生成的构造函数,如:类中的成员变量大多都是自定义类型,对于内置类型可以通过设定默认值进行初始化,对于自定义类型会调用其默认构造函数进行初始化。这些类的默认构造函数就能满足需求可以不写。
  3. 每个类最好都要提供默认构造函数:像Date类的默认构造函数会调用Time类的默认构造函数,此时不写Time类的默认构造函数就会编译出错。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/448449.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Pytorch深度学习笔记(六)用pytorch实现线性回归

目录 1.数据准备 2.设计模型 3.构造损失函数和优化器 4.训练周期&#xff08;前馈—>反馈—>更新&#xff09; 课程推荐&#xff1a;05.用PyTorch实现线性回归_哔哩哔哩_bilibili 线性通常是指变量之间保持等比例的关系&#xff0c;从图形上来看&#xff0c;变量之间…

为什么要学习微服务?

文章目录 1.认识微服务1.1微服务由来1.2为什么需要微服务&#xff1f; 2.两种架构2.1.单体架构2.2.分布式架构 3.微服务的特点4.SpringCloud5.总结最后说一句 1.认识微服务 随着互联网行业的发展&#xff0c;对服务的要求也越来越高&#xff0c;服务架构也从单体架构逐渐演变为…

类和对象(上篇)

类和对象----上篇 &#x1f506;面向过程和面向对象的初步认识&#x1f506;类的引入&#x1f506;类的定义&#x1f506;类的访问限定符及封装访问限定符封装 &#x1f506;类的作用域&#x1f506;类的实例化&#x1f506;类的对象大小的计算如何计算一个类的大小结构体内存对…

15天学习MySQL计划(多表联查)第四天

15天学习MySQL计划&#xff08;多表联查&#xff09;第四天 1.多表查询 1.1概述 ​ 指从多张表中查询数据 ​ 在项目开发中&#xff0c;在进行数据库表结构设计时&#xff0c;会根据业务需求及业务模块之间的关系&#xff0c;分析并设计表结构&#xff0c;由于业务之间相互…

【HCIP】Huawei设备下IPV4IPV6共存实验

目录 方法一、普通的GRE将V6基于V4通讯 方法二、6to4的tunnel 方法三、双栈 方法一、普通的GRE将V6基于V4通讯 //方法一和方法二的前提&#xff0c;搭个简单的V4网络就行 [r1]int g0/0/0 [r1-GigabitEthernet0/0/0]ip address 12.1.1.1 24 [r1]router id 1.1.1.1 [r1-Gigabi…

Spring Security 05 密码加密

目录 DelegatingPasswordEncoder 使用 PasswordEncoder 密码加密实战 密码自动升级 实际密码比较是由PasswordEncoder完成的&#xff0c;因此只需要使用PasswordEncoder 不同实现就可以实现不同方式加密。 public interface PasswordEncoder {// 进行明文加密String encod…

如何搭建自己的博客网站(手把手教你搭建免费个人博客网站)

没有前言直接开始正文&#xff0c;搭建一个博客需要服务器&#xff0c;域名&#xff0c;博客程序。 博客程序常用的有wordpress&#xff0c;z-blog&#xff0c;typecho等等&#xff0c;其中wordpress和z-blog最为简单&#xff0c;typecho需要一定的技术含量&#xff0c;这里暂…

使用NPOI做Excel简单报表

文章目录 前言初版表格&#xff0c;单元格的合并进阶表格&#xff0c;单元格美化小结 前言 前面介绍了NPOI单元格样式的使用、单元格合并&#xff0c;以及NPOI提供的颜色。现在用上前面的一些知识点&#xff0c;做一个测试结果表格。 1、 介绍NPOI 的颜色卡、名称以及索引 ht…

图片去摩尔纹简述实现python代码示例

这篇文章主要为大家介绍了图片去摩尔纹简述实现的python代码示例&#xff0c;有需要的朋友可以借鉴参考下&#xff0c;希望能够有所帮助&#xff0c;祝大家多多进步&#xff0c;早日升职加薪 1、前言 当感光元件像素的空间频率与影像中条纹的空间频率接近时&#xff0c;可能产生…

分布式系统需要关注的技术点和面试经常问的点

1、分布式系统概述 关于什么是分布式系统&#xff0c;有很多文章介绍&#xff0c;其实这个并不难理解&#xff0c;大白话讲就是&#xff1a;工厂活多了一个人撑不住&#xff0c;那就多找些工人一起干&#xff0c;要让这么多人为了一个目标干得快干得好&#xff0c;就需要一些规…

自主可控智能网联汽车操作系统

开发自主可控智能网联汽车操作系统的必要性 当下&#xff0c;传统汽车操作系统行业的核心技术几乎由国外的黑莓、谷歌、风河、Vector、ETAS等垄断。操作系统已成为我国智能网联汽车发展过程中的关键卡脖子技术&#xff0c;开发自主可控的智能网联汽车操作系统势在必行。 操作…

CVPR 2023 | 达摩院REALY头部重建榜单冠军模型HRN解读

团队模型、论文、博文、直播合集&#xff0c;点击此处浏览 前言 高保真 3D 头部重建在许多场景中都有广泛的应用&#xff0c;例如 AR/VR、医疗、电影制作等。尽管大量的工作已经使用 LightStage 等专业硬件实现了出色的重建效果&#xff0c;从单一或稀疏视角的单目图像估计高精…

微服务架构设计与实践

随着互联网的发展&#xff0c;软件开发已经成为各种企业发展的重要手段。然而&#xff0c;单体应用在长时间的维护中会变得复杂、难以扩展、难以修改。因此&#xff0c;为了满足业务需求&#xff0c;微服务架构应运而生。本篇文章将深入探讨微服务架构的设计与实践。 一、微服务…

C++中的类与对象

类与对象 我们在C语言中自定义的struct 叫做结构体&#xff0c;而在C中我们把struct升级为了类&#xff0c;并且还加入了一个class&#xff0c;也称为类&#xff0c;那么我们今天就来看一下结构体和类的不同和相同 1.结构体与类 我们在C语言中的结构体是struct&#xff0c;而…

QT学习笔记(持续更新)

QT 一、按钮 1.效果 2.代码 #include<QPushButton>//头文件myWidget::myWidget(QWidget *parent): QWidget(parent) {//方法1QPushButton *btnnew QPushButton;//btn->show();//以顶层方式显示btn->setParent(this);//在myWidget窗口中btn->setText("按钮…

JS编程中的API hook

JavaScript奇技淫巧&#xff1a;Hook与反Hook 作者&#xff1a;专注于JS混淆加密的 JShaman API HOOK技术&#xff0c;在PC时代曾盛行&#xff0c;是高端的技术。在JavaScript编程中&#xff0c;也可以应用API Hook技术实现不寻常的效果。 例&#xff0c;eval hook&#xff1a…

Kotlin 基础 笔记

这里写目录标题 变量函数条件语句if/else 语句when 语句if/else 表达式 和 when 表达式 Kotlin 中的null使用 ?: Elvis 运算符 类和对象构造函数类之间的关系可见性修饰符定义属性委托 变量 变量是存储单项数据的容器&#xff0c;必须先声明变量&#xff0c;才可以使用。 常见…

Centos7.5 如何安装Bacula 11.05详细教程

环境: 本地华为桌面云服务器环境 Centos 7.5 Bacula 11.05 问题描述: Centos7.5 如何安装Bacula 解决方案: 一、官网下载Bacula 1.下载Source Files11.0.5 2.先安装C 和 C++ 编译器 root@localhost ~]# yum install -y gcc gcc-c++ 1 已安装: 2 gcc.x86_64 0:…

梦想云图Node.JS服务(2023.4.19)

说明 后台提供梦想Node.JS服务&#xff0c;方便调用控件后台功能&#xff0c;Windows服务程序所在目录:Bin\MxDrawServer\Windows&#xff0c;Linux服务程序所在目录:Bin\Linux\MxDrawServer 启动服务 Windows:进入Bin\MxDrawServer\Windows目录&#xff0c;运行start.bat启动…

redis原理及进化之路

Redis 的主从复制经历了多次演进&#xff0c;本文将从最基本的原理和实现讲起&#xff0c;并层层递进&#xff0c;逐步呈现 Redis 主从复制的演进历史。大家将了解到 Redis 主从复制的原理&#xff0c;以及各个改进版本解决了什么问题&#xff0c;并最终看清 Redis 7.0 主从复制…