C++--类与对象(二)

类的六个成员函数

如果一个类中什么成员都没有,简称为空类。
空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员
函数。
默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数。
class Date {}; //空类

构造函数

构造函数是一种特殊的成员函数,在C++中用于初始化对象的数据成员。当创建一个类的对象时,构造函数会自动调用,用于确保对象被正确初始化。构造函数的主要作用是为对象提供合适的初始状态,使其能够正常工作。

构造函数的概念可以总结为以下几点:

  1. 初始化对象:构造函数负责为对象的数据成员赋予合适的初始值,确保对象处于一个有效的状态。

  2. 与类同名:构造函数的名称与类名相同,因此可以用来标识对象的类型。

  3. 没有返回类型:与普通函数不同,构造函数没有返回类型,包括 void。因为它们的作用是初始化对象,而不是返回值。

  4. 自动调用:构造函数在对象创建时自动调用,无需手动调用。当对象被声明时,构造函数会立即执行。

  5. 可以有多个重载:同一个类可以有多个构造函数,它们可以根据参数的不同进行重载。这样可以提供多种不同的初始化方式。

  6. 可以带默认参数:构造函数可以像普通函数一样拥有默认参数,从而提供更灵活的对象初始化方式。

构造函数在类的设计中非常重要,它决定了对象在创建时的初始状态,为后续的操作提供了基础。

#include <iostream>
using namespace std;
class Date
{
public:void Print(){cout << _year << "年" << _month << "月" << _day << "日" << endl;}
private:int _year;int _month;int _day;
};
int main()
{Date d1; // 编译器将调用自动生成的默认构造函数对d1进行初始化d1.Print();return 0;
}

这段代码定义了一个简单的日期类 Date,其中包含了三个私有数据成员 _year_month_day,以及一个公有成员函数 Print() 用于输出日期信息。

main() 函数中,创建了一个 Date 类型的对象 d1,由于没有显式地定义构造函数,编译器会自动生成一个默认构造函数。默认构造函数会对对象的数据成员进行默认初始化,对于基本数据类型,如 int,默认初始化会使其值未定义,即可能是随机值。然后调用对象的 Print() 函数输出日期信息。

这段代码的运行结果可能是这样的(由于 _year_month_day 的值未定义,输出的结果会有所不同)

虽然在我们不写的情况下,编译器会自动生成构造函数,但是编译器自动生成的构造函数可能达不到我们想要的效果,所以大多数情况下都需要我们自己写构造函数。

析构函数

析构函数是一种特殊的成员函数,在C++中用于释放对象占用的资源,并在对象生命周期结束时自动调用。它的作用与构造函数相反,用于清理对象在生命周期中分配的资源,以防止资源泄漏和内存泄漏。

析构函数的概念可以总结为以下几点:

  1. 释放资源:析构函数负责释放对象占用的资源,包括动态分配的内存、打开的文件、建立的网络连接等。它确保在对象被销毁之前,所有分配的资源都被正确释放,以避免资源泄漏。

  2. 与类同名:析构函数的名称由波浪号(~)后跟类名构成,与构造函数相似,但前面有一个波浪号。

  3. 没有参数:析构函数不接受任何参数,也没有返回类型,包括 void。它只负责清理对象的资源,不返回任何值。

  4. 自动调用:析构函数在对象生命周期结束时自动调用,无需手动调用。当对象离开其作用域、被删除或程序结束时,析构函数会自动执行。

  5. 只有一个:每个类只能有一个析构函数,不允许重载。如果没有显式地定义析构函数,编译器会自动生成一个默认的析构函数。

析构函数在类的设计中非常重要,它确保对象在销毁时资源被正确释放,避免内存泄漏和资源泄漏问题。

class Date
{
public:Date()// 构造函数{}~Date()// 析构函数{}
private:int _year;int _month;int _day;
};
  • 析构函数 ~Date():这是一个析构函数,用于在对象被销毁时释放资源。在这个示例中,析构函数也是一个空函数,没有实际的清理工作。因为在这个简单的示例中,Date 类并没有分配动态资源,所以不需要显式地释放资源。然而,通常情况下,析构函数会负责释放类对象可能持有的资源,如动态分配的内存、打开的文件句柄等。

 拷贝构造函数

拷贝构造函数是一种特殊的成员函数,在C++中用于通过复制已存在对象的数据创建新对象。当一个对象被传递给函数参数、以值传递方式返回或者通过赋值操作符进行对象赋值时,拷贝构造函数会被调用。

拷贝构造函数的概念可以总结为以下几点:

  1. 复制对象:拷贝构造函数的主要作用是创建一个新对象,并将已存在对象的数据成员复制到新对象中。这样可以在不修改原始对象的情况下创建一个相同状态的新对象。

  2. 参数为同类对象的引用:拷贝构造函数的参数通常是对同类对象的引用,表示要复制的对象。

  3. 对象传递和赋值时调用:拷贝构造函数会在对象被传递给函数参数、以值传递方式返回或者通过赋值操作符进行对象赋值时自动调用。

  4. 默认浅拷贝:默认情况下,拷贝构造函数执行浅拷贝,即简单地将原始对象的数据成员复制到新对象中。如果类中存在指针成员等资源,可能需要手动编写拷贝构造函数来实现深拷贝,以防止资源重复释放或指针悬空等问题。

拷贝构造函数在类的设计中非常重要,它允许我们以简单、方便的方式创建对象的副本,并在对象传递和赋值过程中确保数据的正确复制。

#include <iostream>class MyClass {
private:int _data;
public:// 构造函数MyClass(int data) : _data(data) {std::cout << "Constructor called for object with data: " << _data << std::endl;}// 拷贝构造函数MyClass(const MyClass& other) : _data(other._data) {std::cout << "Copy constructor called for object with data: " << _data << std::endl;}// 打印数据成员void printData() const {std::cout << "Data: " << _data << std::endl;}
};int main() {// 创建一个对象并初始化MyClass obj1(10);std::cout << "Object 1: ";obj1.printData();// 使用拷贝构造函数创建一个新对象MyClass obj2 = obj1;std::cout << "Object 2: ";obj2.printData();return 0;
}

这个示例包含了以下特点:

  1. 构造函数:类 MyClass 包含一个构造函数,用于初始化对象的数据成员 _data

  2. 拷贝构造函数:类 MyClass 包含一个拷贝构造函数,用于通过复制已存在对象的数据创建新对象。

  3. 参数为同类对象的引用:拷贝构造函数的参数是对同类对象的引用,即 const MyClass& other

  4. 对象传递时调用:拷贝构造函数会在对象被传递给函数参数时自动调用。在 main() 函数中,我们使用 MyClass obj2 = obj1; 来复制 obj1,这时拷贝构造函数会被调用。

  5. 默认浅拷贝:拷贝构造函数默认执行浅拷贝,即简单地复制 _data 的值。

  6. 输出信息:在构造函数和拷贝构造函数中,我们打印了相应对象的数据成员 _data 的值。

运行结果

Constructor called for object with data: 10
Object 1: Data: 10
Copy constructor called for object with data: 10
Object 2: Data: 10

 赋值运算符重载

赋值运算符重载是一种特殊的成员函数,用于定义用户自定义类型对象的赋值操作行为。通过重载赋值运算符,可以实现自定义类型对象之间的赋值操作,使其行为类似于内置类型。

赋值运算符重载的概念可以总结为以下几点:

  1. 定义对象赋值行为:赋值运算符重载允许程序员重新定义对象之间的赋值操作。这样,可以通过赋值运算符将一个对象的值赋给另一个对象,从而实现自定义类型对象之间的赋值行为。

  2. 成员函数:赋值运算符重载是一个成员函数,它可以在类的内部进行定义。其名称由关键字 operator 后跟赋值操作符 = 构成。

  3. 返回类型为引用:赋值运算符重载通常返回对象的引用,以支持连续赋值操作。这样可以避免不必要的对象复制。

  4. 参数为同类对象的引用:赋值运算符重载的参数通常是对同类对象的引用。这样可以将右操作数的值复制到左操作数中。

  5. 自赋值检查:在实现赋值运算符重载时,通常需要检查是否为自赋值(即左操作数和右操作数指向同一个对象),以避免出现错误。

  6. 深拷贝:在进行赋值操作时,特别是对于包含动态分配资源的自定义类型,通常需要执行深拷贝,确保资源被正确释放和管理。

赋值运算符重载允许程序员自定义类型的赋值操作,使其更加灵活和符合实际需求。通过适当地重载赋值运算符,可以实现对象之间的赋值行为,从而提高代码的可读性和可维护性。

#include <iostream>
using namespace std;class Date {
public:// 构造函数Date(int year = 0, int month = 1, int day = 1) {_year = year;_month = month;_day = day;}// 赋值运算符重载函数Date& operator=(const Date& d) {if (this != &d) {_year = d._year;_month = d._month;_day = d._day;}return *this;}// 打印函数void Print() {cout << _year << "年" << _month << "月" << _day << "日" << endl;}private:int _year;int _month;int _day;
};int main() {// 创建日期对象并打印Date d1(2024, 5, 8);cout << "Original date: ";d1.Print();// 使用赋值运算符重载将一个日期对象赋值给另一个日期对象Date d2;d2 = d1;// 打印赋值后的日期对象cout << "Assigned date: ";d2.Print();return 0;
}

 重载了赋值运算符 =,使得可以将一个 Date 对象的值赋给另一个 Date 对象。在函数中,我们首先进行自赋值检查,然后将右操作数对象的年、月和日分别赋值给左操作数对象。

const成员

onst修饰类的成员函数
 我们将const修饰的类成员函数称之为const成员函数,const修饰类成员函数,实际修饰的是类成员函数隐含的this指针,表明在该成员函数中不能对this指针指向的对象进行修改。 

例如,我们可以对类成员函数中的打印函数进行const修饰,避免在函数体内不小心修改了对象:

	void Print()const// cosnt修饰的打印函数{cout << _year << "年" << _month << "月" << _day << "日" << endl;}

思考下面几个问题(经典面试题):
1.const对象可以调用非const成员函数吗?
2.非const对象可以调用const成员函数吗?
3.const成员函数内可以调用其他的非const成员函数吗?
4.非cosnt成员函数内可以调用其他的cosnt成员函数吗?

答案是:不可以、可以、不可以、可以
解释如下:
 1.非const成员函数,即成员函数的this指针没有被const所修饰,我们传入一个被const修饰的对象,用没有被const修饰的this指针进行接收,属于权限的放大,函数调用失败。
 2.const成员函数,即成员函数的this指针被const所修饰,我们传入一个没有被const修饰的对象,用被const修饰的this指针进行接收,属于权限的缩小,函数调用成功。
 3.在一个被const所修饰的成员函数中调用其他没有被const所修饰的成员函数,也就是将一个被const修饰的this指针的值赋值给一个没有被const修饰的this指针,属于权限的放大,函数调用失败。
 4.在一个没有被const所修饰的成员函数中调用其他被const所修饰的成员函数,也就是将一个没有被const修饰的this指针的值赋值给一个被const修饰的this指针,属于权限的缩小,函数调用成功。

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

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

相关文章

crossover24中文破解版百度云免费下载 crossover永久免激活汉化包安装使用教程 crossover24激活码分享

原则上&#xff0c;我们不提倡各位使用破解版&#xff0c;这是处于对知识产权的保护&#xff0c;也是为了各位的长远利益。使用正版你可以获得更优质的服务和完善的产品功能。 但仍然有部分用户由于预算、使用习惯等原因&#xff0c;需要破解版。所以本文不讲原则&#xff0c;…

华为交换机配置导出备份python脚本

一、脚本编写思路 &#xff08;一&#xff09;针对设备型号 主要针对华为&#xff08;Huawei&#xff09;和华三&#xff08;H3C&#xff09;交换机设备的配置备份 &#xff08;二&#xff09;导出前预处理 1.在配置导出前&#xff0c;自动打开crt软件或者MobaXterm软件&am…

NIOS II实现LED流水灯以及串口输出(DE2-115开发板)

NIOS II实现LED流水灯以及串口输出&#xff08;DE2-115开发板&#xff09; 前言什么是Qsys?什么是NIOSII?注意事项1、管脚配置2、配置NIOSII时的连接3、注意中断配置好后是这样的4、注意名称的配置5、设置双功能引脚 NIOS II的报错代码以及效果演示流水灯输出到电脑串口助手 …

Python模块之Numpy(二)-- 生成各种随机数

对于 NumPy&#xff0c;与随机数相关的函数都在 random 模块中&#xff0c;其中包括可以生成服从多种概率分布随机数的函数&#xff0c;示例如下&#xff1a; #生成10个服从0-1均匀分布的随机数 arr1 np.random.random([2,5]) #也生成10个服从0-1均匀分布的随机数 arr2 np.ra…

数据分析思维——数据埋点笔记,以电商为例

数据埋点 数据分析前提是有数据&#xff0c;数据从哪里来&#xff0c;要选择采集哪些数据都需要考虑。如某些app上的商品推荐&#xff0c;是基于哪些信息来预判的呢&#xff1f;因此作为数据分析师有必要系统的了解用户行为到用户数据的整个过程 何为数据埋点 每当用户在客户端…

字节码基础

基本概念 java中的字节码&#xff0c;英文bytecode。是java代码编译后的中间代码格式。JVM需要读取并解析字节码才能执行相应的任务。java字节码是JVM的指令集。JVM加载字节码格式的class文件。校验之后通过JIT编译器转换成本机机器代码执行。 java字节码简介 1、java byteco…

【Qt 学习笔记】Qt常用控件 | 布局管理器 | 水平布局Horizontal Layout

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Qt常用控件 | 布局管理器 | 水平布局Horizontal Layout 文章编号&…

leetcode刷题:买卖股票的最佳时机

题目 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票&#xff0c;并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。 返回你可以从这笔交易中获取的最大…

Java基于Geth1.8实现节点同步、合约部署,以及踩坑记录—主节点控制台卡死、节点同步出错的解决方案

前言&#xff1a;本文将从一个区块链入门小白的视角&#xff0c;来一步步的讲解如何实现区块链数据上链&#xff0c;链上数据查询&#xff0c;geth多节点同步。以及讲解在上链过程中&#xff0c;我踩过的坑及其解决方案。如果有不对的地方&#xff0c;还请大佬指教&#xff01;…

2023愚人杯 )————被遗忘的反序列化

<?php# 当前目录中有一个txt文件哦 error_reporting(0); show_source(__FILE__); include("check.php");class EeE{public $text;public $eeee;public function __wakeup(){if ($this->text "aaaa"){echo lcfirst($this->text);}}public functi…

基于SSM+Vue的物流管理系统

运行截图 获取方式 Gitee仓库

用迭代加深解决加成序列问题

可以看到这个最坏的结果是100层搜索&#xff0c;但是其实1 2 4 8 16 32 64 128&#xff0c;到128的话也只要8&#xff0c;所以大概只需要10几层搜索就可以解决了&#xff0c;这个时候就可以用迭代加深的方法&#xff0c;深度一点点的加&#xff0c;如果大于概深度就舍去。有人说…

解决vue3项目打包后部署后某些静态资源图片不加载问题

目录 问题 原因 解决方案 问题 开发完项目打包并部署 然后访问时发现导航栏背景图片没加载 打开浏览器控制台发现这张图片报错404 原因 可能是因为在部署后的服务器环境中对中文文件名的支持不完善。服务器在解析 URL 时可能无法正确识别或编码中文字符&#xff0c;导致无…

实现stract(字符串拼接)函数(C语言)

一、N-S流程图&#xff1b; 二、运行结果&#xff1b; 三、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>int main() {//初始化变量值&#xff1b;char a[80], b[80];int i, n1, n2;//填充字符串&#xff1b;printf("请输入字符串a的内…

Shell编程之循环语句之for

一.for循环语句 读取不同的变量值&#xff0c;用来逐个执行同一组命令 for 变量名 in 取值列表 do命令序列 done 示例&#xff1a; 1.计算从1到100所有整数的和 2.提示用户输入一个小于100的整数&#xff0c;并计算从1到该数之间所有整数的和 3.求从1到100所有整数的偶数和…

【计算机网络】计算机网络体系结构

&#x1f6a9;本文已收录至专栏&#xff1a;计算机网络学习之旅 一.常见的三种结构 (1) OSI参考模型 为了使不同体系结构的计算机网络都能互连起来&#xff0c;国际标准化组织于1977年成立了专门机构研究该问题&#xff0c;提出了著名的开放系统互连基本参考模型&#xff0c…

若依-生成主子表

1. sql语句建表导入到数据库中&#xff1a; -- ---------------------------- -- Table structure for t_ques————主表 -- ----------------------------CREATE TABLE ques (ques_id INT NOT NULL AUTO_INCREMENT COMMENT Id,name VARCHAR(255) NOT NULL COMMENT 测评名称…

IB 公式解析

公式 3.2. Influence Function 影响函数允许我们在移除样本时估计模型参数的变化&#xff0c;而无需实际移除数据并重新训练模型。 3.3 影响平衡加权因子 3.4 影响平衡损失 3.5 类内重加权 m代表一个批次&#xff08;batch&#xff09;的大小&#xff0c;这意味着公式对一个批…

【Dash】开始学习dash

安装Dash 网上很多安装dash的教程&#xff0c;不再赘述 开始Dash 一个dash页面的基本写法 # dash 的基本写法 import dash from dash import html,dcc,callback,Input,Output# 创建一个 dash 应用 app dash.Dash()# 定义布局&#xff0c;定义一个输入框和一个输出框 app.l…

电商技术揭秘营销相关系列文章合集(4)

相关系列文章 电商技术揭秘相关系列文章合集&#xff08;1&#xff09; 电商技术揭秘相关系列文章合集&#xff08;2&#xff09; 电商技术揭秘相关系列文章合集&#xff08;3&#xff09; 文章目录 引言集合说明集合文章列表 引言 在数字化浪潮的推动下&#xff0c;电商行…