构造函数

news2024/10/21 17:38:40

引入:构造函数的由来

对于以下Date类:

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()
{
    //创建一个d1 并且初始化
    Date d1;
    d1.Init(2022, 7, 5);
    d1.Print();
    

    //创建一个d2 并且初始化
    Date d2;
    d2.Init(2022, 7, 6);
    d2.Print();

    return 0;
}

疑问:创建一个对象就得初始化一次, 未免有点麻烦,那能否在对象创建时,就将信息设置进去呢?所以就有了构造函数!

一:构造函数的概念

构造函数 是特殊的成员函数,需要注意的是,构造函数虽然名称叫构造,但是构造函数的主要任
并不是开空间创建对象,而是初始化对象
其特征如下:
1. 函数名与类名相同
2. 无返回值(void都不用写)
3. 对象实例化时编译器 自动调用 对应的构造函数
4. 构造函数可以重载(可以多个构造函数)

二:构造函数的分类

1:无参构造函数(全缺省,无参)->无参构造函数又叫默认构造函数
2:含参构造函数 

三:构造函数的使用

①:无参构造函数

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;

class Date
{
public:
	// 1.无参构造函数
	Date()
	{
		_year = 1;
		_month = 1;
		_day = 1;
	}

void Print()
 {
     cout << _year << "-" << _month << "-" << _day << endl;
 }



private:
	int _year;
	int _month;
	int _day;
};



int main()
{
	Date d1; // 调用无参构造函数

	return 0;
}

结果:

 

②:含参构造函数

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;

class Date
{
public:
	// 2.带参构造函数
	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 d1(1,1,1); // 调用无参构造函数
	d1.Print();

	return 0;
}
结果:

③:全缺省构造函数 

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;

class Date
{
public:
	// 2.带参构造函数
	Date(int year = 1, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}

	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}



private:
	int _year;
	int _month;
	int _day;
};



int main()
{
	Date d1;
	d1.Print();
	Date d2(1, 1, 1); // 调用无参构造函数
	d2.Print();

	return 0;
}

结果:

①②③点的总结:

三种构造函数都可以单独使用,但是需要注意的是,无参构造函数不管是全缺省还是真的没有参数,在用的时候,都不能带括号,否则会变成函数的声明(类似 int Add( ) )

int main()
{
	Date d1;//正确
	Date d2();//错误,成了函数声明

	return 0;
}

④:多个构造函数

class Date {
public:
	//无参构造函数 
	Date() {
		_year = 1;
		_month = 1;
		_day = 1;
	}
	//带参构造函数 
	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(void)
{
	Date d1;// 调用无参构造函数
	d1.Print();

	Date d2(2024, 10, 14);// 调用带参构造函数
	d2.Print();

	return 0;
}

结果:

 

④的总结:

构造函数正如其特征中的第4点,可以重载,但是默认构造函数(全缺省构造函数和无参构造函数)只能存在一个,二者语法上可以共存,但是却因为二义性不能共存

二义性代码展示:

class Date {
public:
	Date() {
		_year = 1;
		_month = 1;
		_day = 1;
	}
	Date(int year = 2024, int month = 10, int day = 14) {
		_year = year;
		_month = month;
		_day = day;
	}

private:
	int _year;
	int _month;
	int _day;
};

int main(void)
{
    //无参,那到底是走无参,还是全缺省???
	Date d1;

	return 0;
}

结果: 

总结:

强烈推荐全缺省的构造函数,因为真的很好用!

代码如下:

#include <iostream>
 
class Date {
    public:
        /* 全缺省 */
        Date(int year = 0, int month = 1, int day = 1) {
            _year = year;
            _month = month;
            _day = day;
        }
    
        void Print() {
            printf("%d-%d-%d\n", _year, _month, _day);
        } 
    private:
        int _year;
        int _month;
        int _day;
};
 
int main(void)
{
    Date d1; // 不传,就是缺省值
    Date d2(2024, 10, 14);
    Date d3(2024);
    Date d4(2024, 10);
 
    d1.Print();  // 0-1-1
    d2.Print();  // 2024-10-14
    d3.Print();  // 2024-1-1
    d4.Print();  // 2024-10-1
 
    return 0;
}

四:C++编译器自动生成的无参默认构造函数

Q:如果我们不在类中,显式的写构造函数呢,系统会做什么吗?

A:会的,C++编译器会自动生成的无参默认构造函数

那C++编译器生成的构造函数,会对成员变量做什么呢?

无构造函数代码:

class Date
{

public:



private:
	int _year;
	int _month;
	int _day;
};

int main(void)
{
	//C++编译器生成的是无参构造函数
	//所以也不能带(),否则成为函数声明
	Date d1;

	return 0;
}

结果:

 

发现其还是随机值?那岂不是什么都没做?

解释:

C++ 把类型分成内置类型 ( 基本类型 ) 和自定义类型。内置类型就是语言提供的数据类型,如:int/char... ,自定义类型就是我们使用 class/struct/union 等自己定义的类型,看看下面的程序,就会发现编译器生成默认的构造函数会对其内置类型的变量不作初始化,对其自定类型成员_t 调用的它的默认构造函数

①:自身类中没有显式定义构造函数,但成员变量中的自定义变量有默认构造函数(无参)

class Time
{
public:
	Time()
	{
		cout << "Time()" << endl;//打印了Time(),就代表这个构造函数被调用了
		_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;
}

结果:

 

解释:正如前文所说, 会对其内置类型的变量不作初始化,对其自定类型成员_t调用的它的默认构造函数

②:自身类中没有显式定义构造函数,但成员变量中的自定义变量有默认构造函数(全缺省)

class Time
{
public:
	Time(int hour = 8, int minute = 24, int sconde = 5)
	{
		cout << "Time()" << endl;//打印了Time(),就代表这个构造函数被调用了
		_hour = hour;
		_minute = minute;
		_second = sconde;
	}
private:
	int _hour;
	int _minute;
	int _second;
};
class Date
{
private:
	// 基本类型(内置类型)
	int _year;
	int _month;
	int _day;
	// 自定义类型
	Time _t;
};
int main()
{
	Date d;
	return 0;
}

结果:

 

③:自身类中没有显式定义构造函数,但成员变量中的自定义变量有含参的构造函数(非默认)

class Time
{
public:
	Time(int hour, int minute, int seconf)
	{
		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;
}

结果:

 

自身类中没有显式定义构造函数,且成员变量中的自定义变量也没有构造函数

 

class Time
{
public:
	//无构造函数
private:
	int _hour;
	int _minute;
	int _second;
};
class Date
{

private:
	// 基本类型(内置类型)
	int _year;
	int _month;
	int _day;
	// 自定义类型
	Time _t;
};
int main()
{
	Date d;
	return 0;
}

结果:

 

解释:都是随机值,但是可以看出,d的内置类型随机值是因为C++编译器生成的默认构造函数造成的,自定义类型_t 的成员变量也是随机值,这也是C++为Time类自动生成的默认构造函数造成的,都是随机值,但是这也是对类型的一种处理

补充:

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:

	// 基本类型(内置类型)
	int _year = 2024;
	int _month = 10;
	int _day = 14;
	// 自定义类型
	Time _t;
};
int main()
{
	Date d;
	return 0;
}

结果:

总结:

C++ 编译器生成默认的构造函数会对其内置类型的变量不作初始化,对其自定类型成员_t 调用的它的默认构造函数(不写自动生成的默认构造函数,写的无参或全缺省),根据默认构造函数来初始化,且含参的构造函数会报错。

 

 

 

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

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

相关文章

STL源码剖析:STL算法

STL 算法总览 质变算法 mutating algorithms—会改变操作对象之值 所有的 STL算法都作用在由迭代器(first,last)所标示出来的区间上。所谓“质变算法”,是指运算过程中会更改区间内(迭代器所指)的元素内容。诸如拷贝(copy)、互换(swap)、替换(replace)、填写(fill)、删除(remov…

吐槽kotlin之垃圾设计

本文重点在于吐槽垃圾设计&#xff0c;基本直只说缺点。 一.没有static关键字 static其实不是很面向对象&#xff0c;但是是很有必要和方便的。 kotlin为了实现java的static功能&#xff0c;必须使用伴生类&#xff0c;一般情况下没啥问题&#xff0c;但是反编译之后的class多…

数据结构与算法——Java实现 36.求数据流中位数

就借着月光&#xff0c;再与你对望 —— 24.10.14 295. 数据流的中位数 中位数是有序整数列表中的中间值。如果列表的大小是偶数&#xff0c;则没有中间值&#xff0c;中位数是两个中间值的平均值。 例如 arr [2,3,4] 的中位数是 3 。例如 arr [2,3] 的中位数是 (2 3) / 2 …

Java jconsole.exe 调试工具

寻找JDK所在路径&#xff1a; 打开 jconsole.exe 启动之前确保idea程序已经运行了有的同学需要用管理员方式运行&#xff0c;即 右键 jconsole.exe 选择用管理员方式运行 上面的折线图&#xff0c;表示随着时间有哪些线程 下面的左边的线程中&#xff1a;Thread tnew MyThre…

【Java数据结构】链表面试题

【Java数据结构】链表面试题 一、移除链表元素二、反转链表三、链表的中间结点四、删除链表的倒数第 N 个结点五、合并两个有序链表六、链表分割七、链表的回文结构八、相交链表九、环形链表 此篇博客希望对你有所帮助&#xff08;帮助你更加了解链表&#xff09;&#xff0c;不…

stm32 为什么有2个晶振?8mhz+32.768k

1个是系统时钟晶振是单片机内部系统的主时钟源&#xff0c;它负责控制整个系统的时钟频率。这个晶振的频率一般比较高&#xff0c;通常在几十MHz到几百MHz不等。它和CPU以及各种总线之间相互配合&#xff0c;从而协同工作。 另外一个是外设时钟晶振则通常用于单片机的内部外设…

pnpm报错 cannot find package xxx,有的电脑正常运行,只有这个的电脑报错

pnpm build报错 cannot find package xxx&#xff0c;有的电脑正常运行&#xff0c;只有这一个报错 在网上查找各种资料发现是项目在电脑里的目录层级比较深导致的。 问题&#xff1a;在 Windows 系统上&#xff0c;文件路径过长&#xff08;超过 260 个字符&#xff09;可能…

2024年10月14日读书笔记第三篇-

我们继续学习 自下而上思考&#xff0c;总结概括 如果你将所有的信息进行归类分组、抽象概括&#xff0c;并以自上而下的方式表达出来&#xff0c;那么你的文章结构会如图1-3所示。每个方框代表你希望表达的一个思想。 你的思维从最底部的层次开始构建&#xff0c;将句子按照某…

CUDA 事件计时

CUDA 事件 可以为主机代码和设备代码计时。 基本的语法 // 定义事件变量 cudaEvent_t start, stop; // 初始化 cudaEventCreate(&start); cudaEventCreate(&stop); // 记录代表时间开始的事件&#xff0c;注意不是地址 cudaEventRecord(start); // 在TCC的驱动下可以…

【网络安全】1,600$:Auth0 错误配置

未经许可,不得转载。 文章目录 前言正文漏洞案例修复建议前言 Auth0 是一个广泛用于网站和应用程序的身份验证平台,负责管理用户身份并确保其服务的安全访问。该平台提供了多种工作流程,以无缝集成登录和注册流程。 在 Auth0 中创建新应用时,注册选项默认启用。当系统禁用…

Go 1.19.4 命令调用、日志、包管理、反射-Day 17

1. 系统命令调用 所谓的命令调用&#xff0c;就是通过os&#xff0c;找到系统中编译好的可执行文件&#xff0c;然后加载到内存中&#xff0c;变成进程。 1.1 exec.LookPath&#xff08;寻找命令&#xff09; 作用&#xff1a; exec.LookPath 函数用于在系统的环境变量中搜索可…

【每日刷题】Day139

51. N 皇后 - 力扣&#xff08;LeetCode&#xff09; //思路&#xff1a;DFS哈希。 //本题的难点就在于剪枝操作。 class Solution { public: int n; vector<vector<string>> ans; vector<string> path; bool cols[10], dig1[20], dig2[20]; void dfs(int ro…

【无标题】基于情境依赖因果影响的多智能体协作强化学习

、文章探讨了大型语言模型&#xff08;LLMs&#xff09;&#xff0c;例如GPT-4&#xff0c;是否以及在何种意义上拥有知识。作者认为&#xff0c;这些模型展现了一种称为“工具性知识”的能力&#xff0c;这种知识允许它们根据输入上下文推断任务结构&#xff0c;并在此基础上进…

appium启动hbuild打包的apk异常解决

目录 一、错误信息 二、问题解决 2.1 通过以下命令获取安装包名称&#xff1a; 2.2 这个launcher状态下的安装包名称和active&#xff0c;替换原先的安装包名称 一、错误信息 通过adb shell dumpsys activity | findstr "mResume" 命令获取的安装包信息&#xff…

2024年公路水运工程施工企业主要负责人证模拟考试题库及公路水运工程施工企业主要负责人理论考试试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年公路水运工程施工企业主要负责人证模拟考试题库及公路水运工程施工企业主要负责人理论考试试题是由安全生产模拟考试一点通提供&#xff0c;公路水运工程施工企业主要负责人证模拟考试题库是根据公路水运工程施…

芯课堂 | 使用 SWM341 系列 MCU 环境配置

SWM341系列MCU调试环境配置 SWM341 是华芯微特的其中一款 MCU&#xff0c;341 和 341内置 SDRAM 的 34S 系列&#xff0c;其内核相同。 芯片使用安谋科技“星辰”STAR-MC1 内核,基于 Arm-V8 指令集架构&#xff0c;下载烧录选 M33&#xff0c;对应的工具需要升级; 1、使用 KE…

MySQL中库的操作

目录 前言 一、查看数据库 1.1、语法 二、创建数据库 2.1、语法 2.2、自定义⼀个数据库 2.2.1、创建一个名为“aokey”的数据库 三、字符集编码和校验(排序)规则 3.1、查看数据库支持的字符集编码 3.2、查看数据库支持的排序规则 3.3、不同的字串集与排序规则对数…

芯片供电引脚为什么要放一个104电容?

每个芯片的电源都要接一个104电容是为什么? 这颗电容叫高频旁路电容&#xff0c;作用就是把电源中的高频杂波对地短路防止高频污染&#xff0c;降低电源输入对芯片的影响。 接地滤波电容&#xff0c;如果没有&#xff0c;杂波干扰非常大&#xff0c;有了这个滤波电容&#x…

Json-Rpc框架(项目设计 —— 服务端客户端 模块功能划分简介)

阅读导航 引言一、理解项目功能⭕分布式RPC服务发现/注册/订阅/创建 结构图⭕项目三大核心功能 二、服务端模块划分简介三、客户端模块划分简介 引言 在上一篇文章中&#xff0c;我们深入探讨了Json-Rpc框架中不可或缺的序列化与反序列化利器——JsonCpp库。 在本篇文章中&am…

Python酷玩之旅_如何正确使用pipreqs完成依赖导出(解决UnicodeDecodeError)

导览 前言Q&#xff1a;如何正确使用pipreqs1. 安装库2. 命令详解2.1 options2.2 path 3. 实践与问题 结语系列回顾 前言 使用python开发的应用在迁移部署的时候&#xff0c;你一定会使用pipreqs&#xff08;当然也有其他选择&#xff09;吧&#xff1f;这是一款强大的依赖管理…