首页 > 编程语言 >C++-类和对象(2)默认成员函数

C++-类和对象(2)默认成员函数

时间:2024-01-25 16:32:44浏览次数:32  
标签:函数 成员 默认 编译器 C++ 重载 构造函数

在上一篇博客中,和大家分享了C++中类和对象的定义,类的大小的计算等知识,那么如果C++中一个自定义类中不定义任何的成员变量和成员函数,那么这个类中就是一个什么都没有的空类了吗?实际上,如果在一个类中,如果类中什么成员都不定义,编译器会自动生成6个默认成员函数

接下来借助一个自定义MyDate自定义日期类详细说明C++类中的各个默认成员函数。

C++-类和对象(2)默认成员函数_默认成员函数

默认成员函数:

1.默认成员函数定义:

如果类中未显式定义,编译器会自动生成的成员函数,即为默认成员函数。

2.默认成员函数构成:

C++中类的默认成员函数有:构造函数、析构函数、拷贝构造函数、赋值重载函数、取地址重载(普通对象取地址重载、const对象取地址重载)。


C++-类和对象(2)默认成员函数_析构函数_02

3.各成员函数详解:

3.1构造函数:

作用:初始化类对象成员属性。即实例化一个类对象后,给对象的成员属性赋初值。

特征:

  • 函数名是类名
  • 无返回值
  • 创建对象时自动调用
  • 构造函数可以重载,即对象成员有多种初始化形式

C++-类和对象(2)默认成员函数_拷贝构造_03

例如:MyDate类的构造函数,实现实例化一个MyDate类对象时,对各个成员初始化。

类型:

构造函数支持重载,所以可以实现多种形式的类的构造函数。例如:对MyDate类,还可以提供其他形式的构造函数。也可以用缺省参数实现构造函数。

带参构造函数:

C++-类和对象(2)默认成员函数_成员函数_04

全缺省构造函数:

C++-类和对象(2)默认成员函数_构造函数_05

通过上例可以看出,构造函数实际上起到的是初始化成员属性的作用,构造函数特殊之处有两个,一、实例化对象时,构造函数自动调用。二、如果我们没有实现类的构造函数,编译器会自动生成一个构造函数。但是一旦我们实现了任意一种格式的构造函数,编译器就不会自动生成了。

C++-类和对象(2)默认成员函数_析构函数_06

如上图,当我们实现了构造函数时,实例化时自动调用,无需显式调用,即可初始化。

C++-类和对象(2)默认成员函数_默认成员函数_07

如上图,如果我们未实现构造函数,则编译器自动生成一个构造函数,但是在监视窗口中可以看到d1成员属性并未初始化,而是随机值,这是因为编译器自动生成的构造函数对内置类型成员不处理,所以此时d1的year_、month_、day_属性均未初始化。

C++中成员类型:

内置类型:语言提供的类型,例如:int、char、所有类型的指针...

自定义类型:利用class或者struct关键字自己定义的类。

我们未实现构造函数,编译器自动生成的构造函数,对内置类型不处理,对自定义类型调用其默认构造函数。

易混淆概念:

默认构造函数:默认构造函数是指无需传参的构造函数,包括无参构造,全缺省的构造函数,编译器自动生成的构造函数。

默认构造函数在无参实例化时不能同时存在,原因是调用存在歧义。

默认成员函数:类中的特殊成员函数,程序员未实现时,由编译器自动生成。

针对编译器默认生成的默认构造函数对内置类型成员属性不处理,C++11给出了补丁,即可以在声明成员属性时给出缺省值。如下图,即在声明时给出缺省值,实现自动生成的构造函数也可以对内置类型成员处理。

C++-类和对象(2)默认成员函数_析构函数_08

特殊强调:

构造函数的作用:不是创建一个类对象,而是初始化类对象成员。

3.2析构函数:

定义:

类默认成员函数之一,完成类对象的资源清理工作。

注意:是完成资源清理工作,而非销毁对象。

特征:

  • 函数名是类名前面加一个“~”
  • 无返回值
  • 没有参数,析构函数不能重载
  • 对象生命周期结束时,由编译器自动调用析构函数
  • 如果程序员未实现,由编译器自动生成,对内置类型不处理,自定义类型调用其析构函数。


3.3拷贝构造函数

定义:

拷贝构造函数也是构造函数的一种,同时也是C++类的默认成员函数。

作用:

可以实现利用一个已有的类对象,初始化实例化出来的一个新的类对象。

特征:

  • 拷贝构造函数是构造函数的一种,函数名为类名,没有返回值
  • 参数必须是类对象的引用,如果使用传值传参,则会引发无穷递归。
  • 拷贝构造作为默认成员函数,如果我们不实现,编译器会自动实现,针对内置类型成员属性进行浅拷贝(值拷贝),针对自定义类型成员属性,调用该类的拷贝构造。

拷贝构造的使用场景:

  • 使用已有的对象初始化实例化的一个新的类对象。自动调用拷贝构造
  • 函数调用时,使用类对象作为参数。自动调用拷贝构造
  • 函数有返回值时,使用类对象作为函数返回值。自动调用拷贝构造
  • 即只要发生拷贝构造一个自定义类的动作,就必须通过调用这个类的拷贝构造函数来实现

函数调用书写格式:以MyDate类对象为例

1.使用已有对象创建初始化一个新的类对象,利用已有的d1对象初始化新的MyDate对象d2(两种书写格式)

MyDate d1;
MyDate d2(d1);
MyDate d2=d1;
3.4赋值重载

介绍赋值重载前,首先介绍一个新的概念-运算符重载。为使自定义类能够像内置类型一样使用一些常见的运算符,C++中引入了运算符重载的概念。运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名以及参数列表,其返回值类型与参数列表与普通的函数类似。

函数名:关键字operator 需要重载的运算符符号。

函数通式:返回值类型 operator操作符(参数列表)

注意点:

  • 函数调用的方法:对象可以直接使用重载的符号,根据符号的类型(单目,双目)等传入相关参数,也可以使用operator重载符号(参数) 的形式来调用函数,运算符重载函数作为成员函数调用时,单目运算符的操作数即为调用函数的对象,双目运算符的左操作数默认为调用函数的类对象,右操作数可利用参数传入。

以MyDate类为例,重载”==“比较运算符。

class MyDate {
private:
	int year_;
	int month_;
	int day_;
public:
	bool operator==(const MyDate& d)
	{
		return year_ == d.year_ && month_ == d.month_ && day_ == d.day_;
	}
	MyDate(int year = 2000, int month = 1, int day = 1)
	{
		year_ = year;
		month_ = month;
		day_ = day;
	}
};


int main()
{
	MyDate d1;
	MyDate d2(2000, 1, 1);
	cout << (d1 == d2) << endl;//注意<< ==运算符的优先级
	return 0;
}
  • 重载操作符必须有一个类类型参数
  • 用于内置类型的运算符,其含义不能改变
  • 作为类成员函数重载时,其形参看起来比操作数数目少1
  • .* :: sizeof ?: . 以上五个运算符不能重载

默认成员函数-赋值重载即实现赋值符号的重载”=“

注意点:

  • 赋值运算符只能重载成成员函数不能重载成全局函数
  • 作为类的默认成员函数,赋值重载如果没有显式实现,编译器会自动生成,对内置类型成员,直接赋值,自定义类型的成员调用对应的赋值重载函数完成赋值。
  • 涉及到资源管理时,简单的赋值存在问题,需要我们自己实现赋值重载。
3.5取地址以及const取地址操作符重载

返回this指针,即指向对象(const对象)的指针

编译器可以自动生成。


以上就是本片博客的全部内容,本片博客主要向大家分享了C++中类的6个默认成员函数,如果文章有不当之处或者错误欢迎在评论区指正或者私信小Q,希望能对大家的学习有所帮助,下期见!^-^

标签:函数,成员,默认,编译器,C++,重载,构造函数
From: https://blog.51cto.com/u_16191221/9415566

相关文章

  • KY196 复数集合C++
    这题难点就是什么是复数的模了吧。然后C++写个优先队列(大根堆)+操作符重载就行了。#include<iostream>#include<string>#include<queue>#include<math.h>usingnamespacestd;structnode{inta;intb;};typedefstructnodeelement;intchange(strings,......
  • C转C++速成浅入浅出系列——STL之map
    本系列为应付考研复试用,知识浅入浅出,很多地方不深究细节原理;如有谬误,欢迎大家指出。map【map:地图、图谱】理解为地图(我感觉跟python的字典【dictionary】一样)。一个map中包含了多个键值对,一个键值对可以理解为一个特殊的结构体。键值对:即包含关键字(即key)和值(即value或data)的......
  • C语言和C++中的空指针区别
    C语言中,空指针是NULL,是一个宏在C++中NULL似乎也可以用,但是C++中的NULL其实是有问题的。C++大佬在设计的时候可能没有考虑全面在C++98中,字面常量0既可以是一个整形数字,也可以是无类型的指针(void*)常量但是编译器默认情况下将其看成是一个整形常量,如果要将其按照指针方式来使......
  • 深入解析C++中sizeof和strlen的奥秘:区别、应用与技巧全揭秘!
     sizeof 和 strlen 是C++中用于处理字符串的两个不同的操作符,它们的作用和使用场景有很大的区别。sizeof操作符:区别:sizeof 是一个运算符,不是一个函数,用于获取一个类型或变量的字节大小。对于数组,sizeof 返回整个数组的字节大小。对于指针,sizeof 返回指针本身的......
  • JavaScript 中 eval() 函数
    JavaScript的eval()函数的作用是将一个字符串作为脚本代码进行解析和执行。它可以动态地执行字符串中的JavaScript代码,并返回执行结果。eval()函数可以用于执行任何有效的JavaScript代码,包括声明变量、定义函数、执行表达式等。eval()函数的语法如下:varformArray=$('#formRec......
  • Hive - 窗口函数
       1、窗口函数分组,分组聚合,聚合开窗函数和排序开窗函数 createtablestudent_scores( idint, studentIdint, languageint, mathint, englishint, classIdstring, departmentIdstring ); idstudentIdlanguagemathenglishclassIddepartme......
  • C转C++速成浅入浅出系列——STL之vector
    本系列为应付考研复试用,知识浅入浅出,很多地方不深究细节原理;如有谬误,欢迎大家指出。vector【vector:矢量,向量】理解为向量、动态数组等。我想在我这种入门阶段,最常用的还是其动态数组的功能。需提供头文件#include<vector>创建可指定数组大小,和所有值的初始值;数组大小初始值......
  • C转C++速成浅入浅出系列——STL之set
    本系列为应付考研复试用,知识浅入浅出,很多地方不深究细节原理;如有谬误,欢迎大家指出。set【setof:集合】理解为集合。特点是①元素各不相同②元素会自动从小到大排序③初始时无法指定其大小需提供头文件#include<set> 创建注意初始时不能指定其大小。(不能说集合里有5个......
  • 函数--递归调用
    1.怎么写出一个递归函数step1,写好公式公式是怎么得出的?一般来说通过数学上的归纳演绎、总结得出,具体看下面的例子。step2,一定要写结束条件这一步比较简单,还是得到公式比较关键。2.走楼梯Description假如有n个台阶,一次只能上1个台阶或2个台阶,请问走到第n个台阶有几种走法?为......
  • c++ openssl加密 解密
    #include<iostream>#include<boost/asio.hpp>#include<boost/beast.hpp>#include<boost/beast/websocket.hpp>#include<boost/asio/spawn.hpp>#include<json.hpp>#include<boost/filesystem.hpp>#include<fstrea......