C++语言学习(五)—— 类与对象(一)

目录

一、类类型的定义

二、类成员的访问控制

2.1 什么是"类内"和"类外"

2.2 对于访问控制属性的说明

三、类类型的使用

3.1 进行抽象

3.2 声明类

3.3 实现类

3.4 使用类

四、构造函数的引入

五、析构函数的引入

六、重载构造函数的引入

6.1 函数重载

6.2 默认参数

七、复制构造函数的引入


一、类类型的定义

类类型的定义是指在面向对象编程中,用来描述某一类对象共同特征和行为的模板或蓝图。类是实例化对象的抽象概念,它定义了对象的属性和行为。以下是对类类型定义的详细概述:

  1. 类的名称:每个类都有一个唯一的名称,用于标识和区分不同的类。类的名称通常使用大驼峰命名法,以便清晰地表达类的含义和作用。

  2. 属性:类的属性是指存储在类中的数据。属性可以是基本数据类型(如整数、浮点数、布尔值等),也可以是其他类的对象。属性用于描述对象的特征。例如,一个人类的属性可以包括姓名、年龄、性别等。

  3. 方法:类的方法是指在类中定义的函数。方法用于实现对象的行为和操作。方法可以访问和操作类的属性,也可以与其他对象进行交互。例如,一个人类的方法可以包括吃饭、睡觉、工作等。

  4. 访问修饰符:类的访问修饰符用于控制类的可见性和访问权限。常见的访问修饰符publicprivateprotectedpublic修饰符表示类对外公开,可以被其他类访问;private修饰符表示类只能在自身内部访问;protected修饰符表示类可以被自身和子类访问。

  5. 构造函数:类的构造函数是特殊的方法,用于创建类的对象。构造函数在对象实例化时被自动调用,用于初始化对象的属性和执行其他必要的操作。一个类可以有多个构造函数,以支持不同的对象创建方式。

综上所述,类类型的定义包括类的名称、属性的定义和方法的定义,以及类的访问修饰符和构造函数。类类型用于描述对象的属性和行为,并提供了一种创建具体对象的模板或蓝图。类类型是面向对象编程的核心概念之一。

二、类成员的访问控制

类成员的访问控制是指在类中定义的属性和方法可以被外部代码访问的程度。

2.1 什么是"类内"和"类外"

在面向对象编程中,"类内"和"类外"是指在类定义内部和外部的概念。

  1. 类内:指的是在类的定义内部,也就是在类的大括号 { } 内部的代码块。在类内部可以定义类的成员(属性和方法),通过关键字 public、private、protected 或默认的包私有访问来控制成员的访问级别。类内的代码可以直接访问类的私有成员和受保护成员。

  2. 类外:指的是在类的定义外部,也就是不在类的大括号 { } 内部的代码块。类外的代码无法直接访问类的私有成员,只能通过类的公共接口来访问类的公共成员。类外的代码可以通过创建类的对象来使用类的公共成员。

类内部的代码可以直接访问类的所有成员,而类外部的代码只能通过类的对象来访问类的公共成员。

2.2 对于访问控制属性的说明

访问控制属性是用来控制类的成员(属性和方法)在类内和类外的可见性和访问性。在面向对象编程中,常见的访问控制属性有以下几种:

  1. Public(公共):被标记为public的成员可以在类内外部的任何地方访问。它们是类的公共接口,可以被其他类的对象直接访问和使用。

  2. Private(私有):被标记为private的成员只能在类的定义内部访问。私有成员对类的外部是隐藏的,其他类的对象无法直接访问私有成员。私有成员一般用于实现类的内部逻辑和数据封装。

  3. Protected(受保护):被标记为protected的成员可以在类内部和子类中访问,但对于类的外部是不可见的。受保护成员主要用于实现类的继承和派生,子类可以通过继承和重写来访问和修改受保护成员。

  4. 默认(包私有):如果在成员前不加任何访问控制属性修饰符,那么它的访问级别为默认的包私有访问。默认访问级别限制了成员的访问范围在同一个包内,对于其他包内的类是不可见的。

通过合理使用这些访问控制级别,可以实现对类成员的封装和保护。封装是面向对象编程的重要概念之一,通过限制对类成员的直接访问,可以提高代码的安全性、可维护性和可复用性。

三、类类型的使用

类类型的使用是指在程序中使用已定义的类。

下面是一个简单的示例代码,演示了如何使用已定义的类:

#include <iostream>// 定义一个类
class MyClass {
private:int myPrivateVar; // 私有成员变量public:int myPublicVar;  // 公有成员变量// 构造函数MyClass(int privateVar, int publicVar) {myPrivateVar = privateVar;myPublicVar = publicVar;}// 成员方法void display() {std::cout << "Private variable: " << myPrivateVar << std::endl;std::cout << "Public variable: " << myPublicVar << std::endl;}
};int main() {// 创建对象并初始化MyClass obj(10, 20);// 调用对象的方法和访问对象的属性obj.display();std::cout << "Public variable value: " << obj.myPublicVar << std::endl;return 0;
}

在上述代码中,首先定义了一个名为MyClass的类,包含一个私有成员变量myPrivateVar和一个公有成员变量myPublicVar,以及一个成员方法display()。在main()函数中,通过创建一个MyClass对象obj并传入初始化参数10 和20 来使用该类。然后,通过调用对象的display()方法和访问对象的myPublicVar属性,对对象进行操作和访问。最后,将对象的公有变量值打印输出。

3.1 进行抽象

抽象是指隐藏实现细节,只暴露必要的接口和属性,分为数据抽象行为抽象

  1. 数据抽象:通过将复杂的数据结构和数据类型抽象为简单的数据类型,只暴露必要的接口来操作和访问数据。可以使用类的成员变量来实现,将其声明为private,只能通过公共接口访问和操作。数据的具体实现细节被隐藏,只能通过定义的接口来操作数据。

  2. 行为抽象:将对象的具体行为和实现细节抽象为类的成员方法和接口,隐藏实现细节,只暴露必要的方法接口。通过定义类的成员方法和接口,将对象的行为抽象为可调用的函数,外部调用者只需知道如何调用方法,无需关心具体实现细节。

通过数据抽象和行为抽象,实现代码的模块化、可重用和易理解。同时提供更好的安全性、封装性,使类的实现细节对外部透明,只需关注功能和接口。

3.2 声明类

声明类的语法如下:

#include <iostream>class MyClass {
public:int getValue(); // 成员函数private:int value; // 私有成员变量
};

在这个例子中,我们声明了一个名为MyClass的类,在类中一个成员函数getValue。私有成员变量value只能通过公有成员函数访问。

3.3 实现类

int MyClass::getValue() {return value;
}

我们接着上述示例代码,在类的外部实现MyClass的成员函数。

 .cpp文件中实现类的成员函数要在类的外部进行,由于这些函数不是类的一部分,所以需要使用::运算符来标识其所属的类。

3.4 使用类

int main() {// 创建对象MyClass obj1;// 调用成员函数std::cout << "Value of obj1: " << obj1.getValue() << std::endl;return 0;
}

在主函数中,我们创建了一个MyClass对象并调用了它们的成员函数。

四、构造函数的引入

构造函数是一种特殊的成员函数,用于在创建对象时初始化对象的数据成员。在C++中,构造函数的名称与类名相同,并且没有返回类型(甚至没有void)。

构造函数可以具有参数,用于接收创建对象时传递的初始化值。构造函数还可以重载,允许多个不同的构造函数用于不同的初始化方式。构造函数还可以设置默认参数值,以便在创建对象时可以省略参数。

下面是一个示例,在类中引入构造函数:

#include <iostream>class MyClass {
public:// 默认构造函数MyClass();// 带参数的构造函数MyClass(int val);// 成员函数声明void setValue(int val);int getValue();private:// 私有成员变量int value;
};// 默认构造函数的定义
MyClass::MyClass() {value = 0;
}// 带参数的构造函数的定义
MyClass::MyClass(int val) {value = val;
}// 成员函数定义
void MyClass::setValue(int val) {value = val;
}int MyClass::getValue() {return value;
}int main() {// 使用默认构造函数创建对象MyClass obj1;std::cout << "Default Value: " << obj1.getValue() << std::endl;// 使用带参数的构造函数创建对象MyClass obj2(10);std::cout << "Value: " << obj2.getValue() << std::endl;return 0;
}

在这个例子中,我们添加了一个默认构造函数和一个带参数的构造函数。默认构造函数没有参数,会将value初始化为0。带参数的构造函数接受一个整数参数,并将其赋值给value。在主函数中,我们分别使用默认构造函数和带参数的构造函数来创建对象,并输出其值。

构造函数可以在对象创建时自动调用,以确保对象正确地初始化。如果没有明确定义构造函数,C++编译器将提供一个默认的无参构造函数,该函数将执行默认的初始化操作。

五、析构函数的引入

析构函数是一种特殊的成员函数,用于在对象销毁时清理对象的资源。它的名称与类名相同,但前面加上了一个波浪符(~)。

析构函数没有参数,也没有返回类型(甚至没有void)。它被自动调用,当对象超出其作用域、被显式删除或程序结束时。

在C++中,析构函数的作用是释放对象在其生命周期内所分配的资源,例如堆内存、打开的文件、网络连接等。我们可以在析构函数中编写清理资源的代码。

下面是一个示例,在类中引入析构函数:

#include <iostream>class MyClass {
public:// 默认构造函数MyClass();// 析构函数~MyClass();// 成员函数声明void setValue(int val);int getValue();private:// 私有成员变量int *ptr;
};// 默认构造函数的定义
MyClass::MyClass() {// 在构造函数中分配内存ptr = new int;*ptr = 0;
}// 析构函数的定义
MyClass::~MyClass() {// 在析构函数中释放内存delete ptr;
}// 成员函数定义
void MyClass::setValue(int val) {*ptr = val;
}int MyClass::getValue() {return *ptr;
}int main() {MyClass obj;obj.setValue(10);std::cout << "Value: " << obj.getValue() << std::endl;return 0;
}

在这个例子中,我们在构造函数中使用new运算符为 ptr成员变量分配了一块动态内存,并将其初始化为0。在析构函数中,我们使用delete运算符释放了这块内存。

在主函数中,我们创建了一个MyClass对象obj,设置了其值,并输出该值。当obj超出其作用域时,即主函数结束时,析构函数会自动被调用,释放 ptr指向的内存。

析构函数的主要作用是确保资源的正确释放,以避免内存泄漏或资源浪费。

六、重载构造函数的引入

重载构造函数是指在同一个类中定义多个具有不同参数列表的构造函数。通过重载构造函数,我们可以根据不同的需求来创建对象,提供更灵活的对象初始化方式。

在C++中,我们可以通过两种方式来重载构造函数:函数重载和默认参数。

6.1 函数重载

函数重载: 函数重载允许在同一个类中定义多个具有不同参数列表的构造函数,它们的名称相同但参数个数、类型或顺序不同。

下面是一个示例,演示了如何使用函数重载来实现多个构造函数:

#include <iostream>class MyClass {
public:// 无参数的构造函数MyClass();// 带一个参数的构造函数MyClass(int val);// 带两个参数的构造函数MyClass(int val1, int val2);// 成员函数声明void setValue(int val);int getValue();private:// 私有成员变量int value;
};// 无参数的构造函数的定义
MyClass::MyClass() {value = 0;
}// 带一个参数的构造函数的定义
MyClass::MyClass(int val) {value = val;
}// 带两个参数的构造函数的定义
MyClass::MyClass(int val1, int val2) {value = val1 + val2;
}// 成员函数定义
void MyClass::setValue(int val) {value = val;
}int MyClass::getValue() {return value;
}int main() {MyClass obj1; // 调用无参数的构造函数,默认初始化为0std::cout << "Value: " << obj1.getValue() << std::endl;MyClass obj2(10); // 调用带一个参数的构造函数,初始化为10std::cout << "Value: " << obj2.getValue() << std::endl;MyClass obj3(5, 7); // 调用带两个参数的构造函数,初始化为12std::cout << "Value: " << obj3.getValue() << std::endl;return 0;
}

在这个例子中,我们定义了三个不同的构造函数,分别是无参数的构造函数、带一个参数的构造函数和带两个参数的构造函数。通过不同的构造函数,我们可以根据不同的情况来创建对象。

6.2 默认参数

默认参数: 默认参数允许在构造函数中为某些参数提供默认值,这样在创建对象时可以省略对应的参数。

下面是一个示例,演示了如何使用默认参数来实现构造函数的重载:

#include <iostream>class MyClass {
public:// 带一个参数的构造函数,默认值为0MyClass(int val = 0);// 成员函数声明void setValue(int val);int getValue();private:// 私有成员变量int value;
};// 带一个参数的构造函数的定义
MyClass::MyClass(int val) {value = val;
}// 成员函数定义
void MyClass::setValue(int val) {value = val;
}int MyClass::getValue() {return value;
}int main() {MyClass obj1; // 调用带默认参数的构造函数,初始化为0std::cout << "Value: " << obj1.getValue() << std::endl;MyClass obj2(10); // 调用带一个参数的构造函数,初始化为10std::cout << "Value: " << obj2.getValue() << std::endl;return 0;
}

在这个例子中,我们在构造函数的参数列表中为参数val提供了默认值0。当创建对象时,如果没有显式地指定参数值,就会使用默认值进行初始化。

七、复制构造函数的引入

复制构造函数是一种特殊的构造函数,用于创建一个对象,该对象的内容和另一个同类型对象完全相同。复制构造函数通常是通过将另一个对象的成员变量的值复制到新对象中来实现的。

在C++中,默认情况下,编译器会为我们自动生成一个默认的复制构造函数。然而,如果我们需要对对象进行深拷贝(即复制对象及其动态分配的资源),或者需要自定义复制构造函数的行为,就需要手动定义复制构造函数。

下面是一个示例,演示了如何手动定义和使用复制构造函数:

#include <iostream>class MyClass {
public:// 构造函数MyClass(int val);// 复制构造函数MyClass(const MyClass& other);// 成员函数声明void setValue(int val);int getValue();private:// 私有成员变量int value;
};// 构造函数的定义
MyClass::MyClass(int val) {value = val;
}// 复制构造函数的定义
MyClass::MyClass(const MyClass& other) {value = other.value;
}// 成员函数定义
void MyClass::setValue(int val) {value = val;
}int MyClass::getValue() {return value;
}int main() {MyClass obj1(10); // 创建一个对象并初始化为10MyClass obj2(obj1); // 使用复制构造函数创建一个新对象,内容和obj1相同std::cout << "Value of obj2: " << obj2.getValue() << std::endl;return 0;
}

在这个例子中,我们手动定义了一个复制构造函数MyClass::MyClass(const MyClass& other),它接受一个同类型的对象作为参数。在复制构造函数中,我们将参数对象的成员变量值复制到新对象中。

main()函数中,我们首先创建了一个对象obj1并初始化为10。然后,通过使用复制构造函数,我们创建了一个新对象obj2,它的值和obj1完全相同。

使用复制构造函数可以方便地创建对象的副本,而无需手动逐个复制成员变量的值。

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

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

相关文章

一文读懂“双随机、一公开”:企业监管新风向

在这个信息透明化、法治化日益增强的时代&#xff0c;政府对企业监管的方式也在不断创新和完善。“双随机、一公开”作为一种新型监管模式&#xff0c;正逐渐成为市场监管领域的关键词。对于企业或个体工商户而言&#xff0c;了解并适应这一监管机制&#xff0c;对于维护自身合…

工具分享:VsCode注释神器,koro1FileHeader

他是有官方Wiki的。 https://github.com/OBKoro1/koro1FileHeader/wiki/ 项目在GitHub上开源。以下摘录部分wiki&#xff0c;用作介绍分享在这里插入代码片 如何找到setting.json设置模板 简单的输入命令 打开VSCode命令面板: mac: command p window: ctrl p输入> Ope…

9.5 Go语言入门(条件语句和循环语句)

Go语言入门&#xff08;条件语句和循环语句&#xff09; 目录四、条件语句和循环语句1. 条件语句1.1 if 语句1.2 if-else 语句1.3 if-else if-else 语句1.4 带初始化语句的 if1.5 switch 语句1.6 带条件的 switch1.7 多个条件的 case 2. 循环语句2.1 基本 for 循环2.2 省略初始…

从零开始搭建SpringCloud Alibaba微服务架构

Spring Cloud Alibaba是Spring Cloud的一个拓展项目&#xff0c;它用于构建基于阿里巴巴的微服务应用。它提供了多个阿里巴巴的开源组件&#xff0c;如Nacos、Sentinel、Dubbo等&#xff0c;用于解决微服务架构中的服务注册、配置管理、流量控制等问题。 Spring Cloud Alibaba…

记.netcore部署到银河麒麟linux服务器过程详解

一.服务器配置 操作系统:银河麒麟桌面操作系统V10 CPU:intel i5 内存:16G 内核:5.10.0.8-generic 未激活 二.运行环境安装 .netcore 6.0 runtime时安装下载离线包 Download .NET 6.0 (Linux, macOS, and Windows) -下载完后进行解压 sudo su #提权 mkdir -p $HOME/…

TikTok“66大促” 你准备好了吗?

TikTok Shop&#xff0c;也称TikTok电商&#xff0c;作为全球最具创新力和影响力的短视频平台之一&#xff0c;一直以来以其独特的娱乐性内容吸引着数以亿计的用户。而在TikTok Shop上购物&#xff0c;现在已经成为众多年轻用户的时尚选择。随着TikTok Shop开放中国商家入驻&am…

Win10【无线显示器】安装失败(无法添加)解决中。。。

目录 ■失败现象 ■解决方法 【服务启动1】 【服务确认】 【服务启动2】 参考 ■查看电脑是否支持【Miracast无线投屏功能】 参考2 ■解决方法&#xff08;对我的这台电脑有效&#xff09; ■解决后的效果 ■连接时&#xff0c;出现【无法在此设备上查看受保护内容。…

通胀担忧仍存,美联储降息预期或又推迟

KlipC报道&#xff1a;周三&#xff0c;美联储公布4月30日至5月1日政策会议纪要&#xff0c;会议纪要显示美联储对通胀仍感到担忧&#xff0c;将更长时间维持利率不变&#xff0c;必要时进一步收紧政策。 尽管在前不久公布的4月CPI数据显示通胀有所缓解&#xff0c;但是被认为…

【Linux】Centos7安装JDK

【Linux】Centos7安装JDK 下载 Oracle 官网下载 JDK17 https://www.oracle.com/cn/java/technologies/downloads/#java17 安装 使用rz命令上传 jdk tar 包&#xff0c;上传失败直接用 xftp 上传 在安装图形界面时&#xff0c;有勾选开发工具&#xff0c;会自动安装 JDK 需要先…

微信小程序反编译/解包

微信小程序反编译/解包 环境与工具 操作系统&#xff1a;Windows 11 23H2 微信版本&#xff1a;3.9.10.19 Q&#xff1a;如何找到小程序文件位置&#xff1f; A&#xff1a;在微信的设置找到文件路径&#xff0c;小程序文件位于 \WeChat Files\Applet\。 Q&#xff1a;小程…

4K高刷显示器 - 10大产品对比

4K高刷显示器 - 蚂蚁电竞 N27U 显示屏评测报告 一、产品品牌知名度 蚂蚁电竞&#xff0c;作为一家专注于电竞领域的品牌&#xff0c;近年来在市场上逐渐崭露头角。虽然相较于一些老牌显示器品牌&#xff0c;蚂蚁电竞的知名度还有待提高&#xff0c;但其在电竞领域的表现却不容…

秋招突击——算法打卡——5/24——无重复字符的最长字串

题目描述 实现代码 // 无重复字符的最长子串 int lengthOfLongestSubstring(string s) {int l 0,r 0;int res 0;unordered_map<char,int> temp;while(l < s.size()){temp[s.at(l)] l;for (r l 1; r < s.size() ; r) {if(temp.count(s.at(r))) break;else te…

漫画|基于SprinBoot+vue的漫画网站(源码+数据库+文档)

漫画网站 目录 基于SprinBootvue的漫画网站 一、前言 二、系统设计 三、系统功能设计 1系统功能模块 2管理员功能模块 3用户功能模块 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a;✌️大…

【Linux学习】进程间通信 (1) —— 管道

下面是有关进程通信中管道的相关介绍&#xff0c;希望对你有所帮助&#xff01; 小海编程心语录-CSDN博客 1. 进程通信的基本概念 1.1 概念 进程间通信简称 IPC &#xff0c;指两个进程之间的通信。 IPC的方式通常有管道&#xff08;包括无名管道和命名管道&#xff09;、消息…

【Linux网络】端口及UDP

文章目录 1.再看四层2.端口号2.1引入linux端口号和进程pid的区别端口号是如何生成的传输层有了pid还设置端口号端口号划分 2.2问题2.3netstat 3.UDP协议3.0每学一个协议 都要讨论一下问题3.1UDP协议3.2谈udp/tcp实际上是在讨论什么&#xff1f; 1.再看四层 2.端口号 端口号(Po…

//TODO 注释的作用

// TODO 用来标记某处&#xff0c;表示该处含有待办事项&#xff08;尚未解决&#xff09;。其设计本意只是提醒开发者注意&#xff0c;除了代码高亮之外&#xff0c;还可以借助编辑器实现快速定位。 如何使用&#xff1f; 直接在双斜杠后面加 TODO 或者 todo 即可&#xff0c…

CVPR2022医疗图像-GBCNet网络:胆囊癌(GBC)超声(USG)图像检测模型

Surpassing the Human Accuracy:Detecting Gallbladder Cancer from USG Images with Curriculum Learning&#xff1a;超越人类的准确性:基于课程学习的USG图像检测胆囊癌 目录 一、背景与意义 二、介绍 三、网络框架 3.1 区域选择网络 3.2 MS-SoP分类器 3.3 多尺度块 …

抖音运营_抖音电商介绍

截止20年8月&#xff0c;抖音的日活跃数高达6亿。 20年6月&#xff0c;上线抖店 &#xff08;抖音官方电商&#xff09; 一 抖店的定位和特色 1 一站式经营 帮助商家进行 商品交易、店铺管理、客户服务 等全链路的生意经营 2 多渠道拓展 抖音、今日头条、西瓜、抖音火山版…

ASP+ACCESS基于WEB社区论坛设计与实现

摘要&#xff1a;系统主要实现BBS网站全部功能。采用目前应用最为广泛的ASP作为开发工具来开发此系统、以保证系统的稳定性。采用目前最为流行的网页制作工具Dreamweaver和目前最为流行的动画制作工具Flash MX。整个系统从符合操作简便、界面友好、灵活、实用、安全的要求出发&…

卤菜销售|基于SSM+vue的智能卤菜销售平台的设计与实现(源码+数据库+文档)

智能卤菜销售平台 目录 基于SSM&#xff0b;vue的智能卤菜销售平台的设计与实现 一、前言 二、系统设计 三、系统功能设计 1系统功能模块 2管理员功能模块 3用户功能模块 4商家功能模块 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八…