C++的面向对象学习(3):面向对象编程的三大特性之:封装

文章目录

  • 前言:C++具有面向对象编程的特性
  • 一、根据前言的例子可以看出,对一个类的设计叫做封装。
    • (1)例一:设计一个圆类,求圆的周长
    • 封装就是对一个类里面的数据属性和函数进行设计定义。对象就是主程序中对这个类的实例化。
  • 二、类的封装怎么感觉跟结构体很像呢??
  • 三、类与对象中的一些常规叫法和术语:
  • 补充:(一)封装中第一个重要的知识:成员的三种访问权限
    • ①封装就好比一个黑盒,对里面成员的权限的设置决定了外界是否能看到和访问里面的成员。
    • ②成员变量的权限一般是私有的。
    • ③保护和私有权限的区别
      • 人话就是:保护的成员,类外不能访问,但是儿子可以访问父亲的保护内容。私有的成员,类外不能访问,而且儿子也不能访问父亲的私有内容。
    • ④成员函数一般是公开的。
  • 补充:(二)封装中第二个重要的知识:封装中能定义数组和结构体吗?一个类里面可以定义另一个类作为成员吗?
  • 补充:(三)封装中的第三个重要知识点:通过函数来自由控制私有成员属性的读写权限
    • 补充:(四)类的封装中,成员的生命周期如何?
      • ①成员的生命周期与实例化的对象的生命周期一致。
      • ②那成员函数里面对成员变量赋值的话,成员变量属于局部变量还是全局变量?


前言:C++具有面向对象编程的特性

在面向对象编程中,类(Class)和对象(Object)是两个重要的概念。

类是一种用户自定义的数据类型,用于封装数据和函数成员。它是一种模板或蓝图,描述了对象的属性和行为。类定义了对象的结构和行为,并提供了一种创建对象的方式

对象是类的实例,通过实例化类来创建的。它是类的具体化,具有类定义的属性和行为。对象是程序中的实体,可以通过对象来访问和操作类的成员。

举个例子,假设我们有一个类叫做"Car",它描述了汽车的属性和行为。在这个类中,我们可以定义数据成员如"color"、“brand"和"speed”,以及成员函数如"start()"、"accelerate()“和"stop()”。当我们实例化这个类时,就创建了一个具体的汽车对象,可以设置它的颜色、品牌和速度,以及调用它的行为函数。

class Car {private:string color;string brand;int speed;public:void start();void accelerate();void stop();
};int main() {Car myCar; // 创建一个名为myCar的汽车对象myCar.color = "Red"; // 设置汽车对象的颜色myCar.brand = "Toyota"; // 设置汽车对象的品牌myCar.speed = 0; // 设置汽车对象的速度myCar.start(); // 调用汽车对象的启动函数myCar.accelerate(); // 调用汽车对象的加速函数myCar.stop(); // 调用汽车对象的停止函数return 0;
}

在上面的例子中,"Car"类描述了汽车的属性和行为,"myCar"对象是"Car"类的一个实例,我们可以通过对象来访问和操作类的成员。

类和对象是面向对象编程的核心概念,它们提供了一种组织和封装代码的方式,使代码更具可读性、可维护性和可扩展性。

一、根据前言的例子可以看出,对一个类的设计叫做封装。

封装的语法:
class 类名{访问权限:数据属性;访问权限:函数行为;}

在面向对象编程中,封装是一种将数据和相关操作封装在一起的机制,以实现数据的隐藏和保护。通过封装,我们可以将数据成员和成员函数组织在类中,并控制对它们的访问权限。

例如设计一个汽车CAR类,它有不同的属性,可以用数据类型来表示,也有不同的行为动作,可以用函数来表示。

class Car {private:string color;string brand;int speed;public:void start(){}void accelerate(){}void stop(){}
};

(1)例一:设计一个圆类,求圆的周长

//例一:设计一个圆类,求圆的周长
#include <iostream>
#include <string>
#include <cmath>
using namespace std;#define PI 3.1415926class Circle {
private://数据成员是私有的float Radius;//圆的半径public://函数成员是公开的void setRadius(float radius) {//利用类的成员函数接口来从外部实现对私有成员圆的半径的操作Radius = radius;}float getCircumference() {//提供给外部的接口函数return 2 * PI * Radius;}float getArea() {return PI * pow(Radius, 2);//提供给外部的接口函数}
};int main() {Circle cir1;//实例化一个圆类的对象cir1float r;cout << "请输入半径:" << endl;cin >> r;cir1.setRadius(r);float Circumference = cir1.getCircumference();float Area = cir1.getArea();cout << "Circumference of the circle: " << Circumference << endl;cout << "Area of the circle: " << Area << endl;system("pause");return 0;
}

setRadius()函数用于设置圆的半径,getCircumference()函数用于计算圆的周长,getArea()函数用于计算圆的面积。
在main()函数中,通过用户输入来设置圆的半径,并计算并输出圆的周长和面积。

封装就是对一个类里面的数据属性和函数进行设计定义。对象就是主程序中对这个类的实例化。

二、类的封装怎么感觉跟结构体很像呢??

观察得很对,类和结构体在某种程度上是相似的,它们都可以用来封装数据和函数成员。实际上,结构体可以看作是一种简化的类

在C++中,结构体(struct)是一种用户自定义的数据类型,可以包含不同类型的数据成员,但默认情况下,结构体的成员是公共的(public)。结构体通常用于组织相关的数据,但不包含复杂的行为。人话就是结构体里面只有数据,没有函数

类(class)也是一种用户自定义的数据类型,与结构体类似,可以包含不同类型的数据成员。但与结构体不同的是,类的成员默认是私有的(private),需要通过公共的成员函数来访问和操作。类可以定义更复杂的行为,包括成员函数、继承和多态等特性

虽然类和结构体有一些相似之处,但它们的主要区别在于使用的目的和特性。类更适合用于面向对象编程,封装数据和行为,实现代码的组织和封装。而结构体更适合用于简单的数据组织,不涉及复杂的行为。

下面是一个使用结构体和类的示例:

// 使用结构体
struct Point {int x;int y;
};// 使用类
class Point {private:int x;int y;public:void setX(int newX) {x = newX;}void setY(int newY) {y = newY;}int getX() {return x;}int getY() {return y;}
};int main() {// 使用结构体Point p1;p1.x = 10;p1.y = 20;// 使用类Point p2;p2.setX(30);p2.setY(40);return 0;
}

在上面的例子中,我们定义了一个结构体"Point"和一个类"Point",它们都包含了两个整型的数据成员"x"和"y"。使用结构体时,我们可以直接访问和修改成员变量。而使用类时,我们需要通过公共的成员函数来设置和获取成员变量的值。

三、类与对象中的一些常规叫法和术语:

类(Class):类是一种抽象的数据类型,用于定义对象的属性和行为。它是对象的模板或蓝图,描述了对象的结构和行为。

对象(Object):对象是类的实例化,是具体的实体。它具有类定义的属性和行为,并可以通过调用类的方法来操作和访问这些属性和行为。

实例化(Instantiate):实例化是创建类的对象的过程。通过实例化,可以根据类的定义创建一个具体的对象。

成员变量(Member Variable):成员变量是定义在类中的变量,用于存储对象的属性。它们也被称为实例变量,因为每个对象都有自己的一组成员变量。

成员函数(Member Function):成员函数是定义在类中的函数,用于操作和访问对象的属性。它们也被称为方法,可以通过对象来调用。

封装(Encapsulation):封装是一种将数据和操作封装在类中的概念。通过将数据和操作封装在类中,可以实现数据的隐藏和保护,只允许通过类的公共接口来访问和操作数据。

继承(Inheritance):继承是一种通过从现有类派生新类的方式来扩展和重用代码的机制。派生类继承了基类的属性和行为,并可以添加自己的特定功能。

多态(Polymorphism):多态是一种允许使用基类类型来引用派生类对象的特性。通过多态,可以以一种统一的方式处理不同类型的对象,提高代码的灵活性和可扩展性。

构造函数(Constructor):构造函数是一种特殊的成员函数,用于在创建对象时初始化对象的状态。它具有与类相同的名称,并且没有返回类型。

析构函数(Destructor):析构函数是一种特殊的成员函数,用于在对象销毁时清理对象的资源。它具有与类相同的名称,前面加上波浪号(~)作为前缀。

补充:(一)封装中第一个重要的知识:成员的三种访问权限

①封装就好比一个黑盒,对里面成员的权限的设置决定了外界是否能看到和访问里面的成员。

成员的访问权限用于控制类的成员(成员变量和成员函数)在类内部和外部的可见性和访问级别。在C++,有三种常见的成员访问权限:公有(Public):公有成员在类内部和外部都是可见和可访问的。 
它们可以被类的对象直接访问,也可以被类的成员函数访问。
公有成员在类的外部可以通过对象名或指针/引用来访问。私有(Private):私有成员只在类内部可见和可访问,对于类的外部是不可见的。
私有成员只能被类的成员函数访问,不能被类的对象直接访问。
私有成员通常用于封装类的实现细节和内部状态。保护(Protected):保护成员在类内部可见和可访问,对于类的外部是不可见的,但对于派生类是可见和可访问的。
保护成员可以被类的成员函数和派生类的成员函数访问。
保护成员通常用于实现继承和派生类的访问控制。

我的理解:三种不同的权限设置决定了类内部的成员能被什么访问。通过控制成员的访问权限,可以实现封装的概念,隐藏类的内部实现细节,提供对外的接口,同时保护数据的安全性和一致性。这样可以提高代码的可维护性、可扩展性和安全性。

②成员变量的权限一般是私有的。

成员变量的权限一般是私有的。将成员变量声明为私有的意味着它们只能在类的内部访问,对于类的外部是不可见的。私有成员变量通常用于封装类的内部状态和实现细节,以保护数据的安全性和一致性。

通过将成员变量设为私有,可以防止外部代码直接访问和修改类的内部数据,只能通过类的公有成员函数来间接访问和修改。这种间接访问和修改的方式提供了更好的控制和封装,使得类的实现细节对外部代码是隐藏的。

举个例子:

class Circle {
private://数据成员是私有的float Radius;//圆的半径public://函数成员是公开的void setRadius(float radius) {//利用类的成员函数接口来从外部实现对私有成员圆的半径的操作Radius = radius;}float getCircumference() {//提供给外部的接口函数return 2 * PI * Radius;}float getArea() {return PI * pow(Radius, 2);//提供给外部的接口函数}
};

圆的半径是私有变量,外界无法用.点运算符来直接访问,而是要通过公开的函数接口setRadius(float radius)来对半径进行赋值。

③保护和私有权限的区别

保护(Protected):保护成员在类内部可见和可访问,对于类的外部是不可见的,但对于派生类是可见和可访问的。
私有(Private):私有成员只在类内部可见和可访问,对于类的外部是不可见的。

人话就是:保护的成员,类外不能访问,但是儿子可以访问父亲的保护内容。私有的成员,类外不能访问,而且儿子也不能访问父亲的私有内容。

④成员函数一般是公开的。

成员函数一般是公开的(即公有成员函数)是因为它们提供了类的外部代码与类进行交互的接口。公有成员函数可以被类的对象直接调用,也可以被类的外部代码通过对象名或指针/引用来调用。

以下是成员函数一般是公开的几个原因:

封装和抽象:公有成员函数定义了类对外部代码提供的接口,通过这些接口,外部代码可以与类进行交互和操作。公有成员函数隐藏了类的内部实现细节,只暴露了必要的操作和功能,实现了封装和抽象的概念

访问控制:公有成员函数可以访问类的私有成员变量,通过公有成员函数,外部代码可以间接地访问和修改类的私有成员变量。这样可以实现对类的内部数据的控制和保护,确保数据的安全性和一致性。

继承和多态:公有成员函数在派生类中可以被继承和重写,从而实现多态性。派生类可以通过继承和重写公有成员函数来扩展和修改基类的行为,实现特定的功能需求。

可访问性:公有成员函数对于类的外部代码是可见和可访问的,可以在外部代码中直接调用。这样可以方便地使用类的功能和操作,提高代码的可用性和可扩展性。

补充:(二)封装中第二个重要的知识:封装中能定义数组和结构体吗?一个类里面可以定义另一个类作为成员吗?

都是可以的。
在封装的概念中,可以定义数组和结构体作为类的成员变量或成员函数的参数、返回值等。
例子一:定义一个数组

class MyClass {
private:int myArray[5]; // 私有数组成员变量public:void setArrayValue(int index, int value) {if (index >= 0 && index < 5) {myArray[index] = value;}}int getArrayValue(int index) {if (index >= 0 && index < 5) {return myArray[index];}return -1; // 返回一个默认值,表示索引无效}
};

例子二:定义一个结构体

class Point {
private:struct Coordinate {int x;int y;} position; // 私有结构体成员变量public:void setPosition(int x, int y) {position.x = x;position.y = y;}int getX() {return position.x;}int getY() {return position.y;}
};

补充:(三)封装中的第三个重要知识点:通过函数来自由控制私有成员属性的读写权限

比如,我有一个人的类,包含三个私有成员变量:年龄、姓名、身高。要求姓名只读,年龄可读可写,身高只写。
那么对着三个变量,最好都用接口函数来进行读取和赋值操作。

class Person {
private:std::string name; // 私有成员变量,姓名int age; // 私有成员变量,年龄double height; // 私有成员变量,身高public:// 读取姓名std::string getName() const {return name;}// 读取年龄int getAge() const {return age;}// 写入年龄void setAge(int newAge) {age = newAge;}// 写入身高void setHeight(double newHeight) {height = newHeight;}
};

补充:(四)类的封装中,成员的生命周期如何?

①成员的生命周期与实例化的对象的生命周期一致。

在类的封装中,成员的生命周期与对象的生命周期紧密相关。成员变量和成员函数的生命周期取决于对象的创建和销毁。

成员变量的生命周期: 成员变量是类的数据成员,用于存储对象的状态信息。当创建一个类的对象时,会为该对象分配内存空间,并在内存中存储对象的成员变量。成员变量的生命周期与对象的生命周期相同,当对象被销毁时,成员变量也会随之销毁。

成员函数的生命周期: 成员函数是类的行为成员,用于操作对象的数据成员。成员函数的生命周期与对象的生命周期相同,当创建一个类的对象时,成员函数也会被创建,并在对象的生命周期内存在。成员函数可以通过对象来调用,以访问和修改对象的成员变量。

需要注意的是,每个对象都有自己的成员变量和成员函数,它们在内存中是独立存储的。这意味着不同对象的成员变量和成员函数是相互独立的,它们的值和行为可以各自独立地进行访问和修改,而不会相互影响。

②那成员函数里面对成员变量赋值的话,成员变量属于局部变量还是全局变量?

在成员函数中对成员变量赋值时,成员变量仍然属于类的成员变量,而不是局部变量或全局变量。

成员函数可以直接访问和修改类的成员变量,因为成员变量是类的数据成员,用于存储对象的状态信息。在成员函数内部,可以使用成员变量的名称来引用它们,并对其进行赋值操作。

尽管在成员函数内部可以直接使用成员变量的名称,但这并不意味着成员变量变成了局部变量。成员变量仍然是属于类的一部分,它们的作用域是整个类,而不仅限于成员函数内部

需要注意的是,成员函数内部的局部变量和成员变量可以具有相同的名称。在这种情况下,成员函数内部的局部变量会遮蔽成员变量,即优先使用局部变量。如果要在成员函数内部访问成员变量而不是局部变量,可以使用成员访问运算符 this-> 来显式指明。

总结起来,成员函数内部对成员变量的赋值操作仍然是对类的成员变量进行赋值,成员变量仍然属于类的一部分,而不是局部变量或全局变量。

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

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

相关文章

CentOS:Docker容器中安装vim

在使用docker容器时&#xff0c;里边没有安装vim时&#xff0c;敲vim命令时提示说&#xff1a;vim: command not found 这个时候就须要安装vim&#xff0c;安装命令&#xff1a; apt-get install vim 出现以下错误&#xff1a; 解决方法&#xff1a; apt-get update 这个命令的…

Spark中使用scala完成数据抽取任务 -- 总结

如题 任务二&#xff1a;离线数据处理&#xff0c;校赛题目需要使用spark框架将mysql数据库中ds_db01数据库的user_info表的内容抽取到Hive库的user_info表中&#xff0c;并且添加一个字段设置字段的格式 第二个任务和第一个的内容几乎一样。 在该任务中主要需要完成以下几个阶…

[Java][File]使用mkdir以及CreateNewFile来制作游戏存档的分级目录+异常抛出机制

文件夹分类&#xff1a; Resource\\Image Resource\\Voice Resource\\VideoInformation\\Characters Information\\mobs Information\\BackpacksPlugin\\Serves Plugin\\Consumers文件的分类&#xff1a; Information\\Characters\\Male.txt Information\\Characters\\Female.t…

刷题记录第五十一天-去除重复字母

题目要求的是字典序最小的结果。只需要理解一点就是按大小顺序排列的字符串的字典序就是最小的&#xff0c;如“abcd”这种。 解题思路如下&#xff1a; 首先明确要使用栈结构&#xff0c;并且是从栈底到栈顶递增&#xff0c;要尽可能保证递增&#xff0c;这样就能保证字典序最…

前端项目常用函数封装(二)

文章目录 前端项目常用函数封装(一)判断两个数组是否有相同元素 返回相同元素&#xff08;数组&#xff09;判断hex颜色值是深色还是浅色随机生成深浅样色 js判断是手机端还是移动端使用UA判断使用媒体查询判断 fetch直接读文件内容&#xff0c;解决乱码问题下载文件将字符串下…

ansibe的脚本---playbook剧本(1)

playbook剧本组成部分&#xff1a; 1、task 任务&#xff1a; 主要是包含要在目标主机上的操作&#xff0c;使用模块定义操作。每个任务都是模块的调用。 2、variables变量&#xff1a;存储和传递数据。变量可自定义&#xff0c;可以在playbook中定义为全局变量&#xff0c;可…

深入理解 Spring Boot:核心知识与约定大于配置原则

深入理解 Spring Boot&#xff1a;核心知识与约定大于配置原则 简单说一下为什么要有 Spring Boot&#xff1f; 因为 Spring 的缺点。 虽然 Spring 的组件代码是轻量级的&#xff0c;但它的配置却是重量级的(需要大量 XML 配置) 为了减少配置文件&#xff0c;简化开发 Spri…

HarmonyOS应用事件打点开发指导

简介 传统的日志系统里汇聚了整个设备上所有程序运行的过程流水日志&#xff0c;难以识别其中的关键信息。因此&#xff0c;应用开发者需要一种数据打点机制&#xff0c;用来评估如访问数、日活、用户操作习惯以及影响用户使用的关键因素等关键信息。 HiAppEvent 是在系统层面…

手机数码品牌网站建设的作用是什么

手机数码产品几乎已经成为成年人必备的&#xff0c;包括手机、电脑、摄像机、键盘配件等&#xff0c;同时市场中相关企业也非常多&#xff0c;消费者可供选择的商品类型也很多样&#xff0c;而对企业来讲&#xff0c;只有不断提升品牌形象、获客拉新等才能不断提升企业地位&…

istio工作负载

目录 文章目录 目录本节实战前言1、WorkloadEntry多实例不同端口权重位置 2、WorkloadGroup关于我最后 本节实战 实战名称&#x1f6a9; 实战&#xff1a;WorkloadEntry测试-2023.12.21(测试成功) 前言 在之前的章节中我们已经多次提到了工作负载&#xff0c;在 Istio 中工作…

《Effective C++》条款42

了解typename的双重意义 作为类模板而言class和typename是一样的。 template <class T> class A {}; template <typename T> class A {}; template <typename C> class A {... private:C::const_iterator* x; }; 这段代码看起来没啥问题。因为我们已经知道它…

CSS中设置盒子大小-box-sizing,设置盒子阴影- box-shadow ,设置盒子圆角-border-radius,属性及其属性值

一&#xff1a;设置盒子大小-box-sizing 默认情况下&#xff1a;盒子可见宽的大小由内容区&#xff0c;内边距&#xff0c;边框共同决定 box-sizing 属性用来设置盒子尺寸的计算方式&#xff0c; 也就是 width/height 指的是谁 可选值&#xff1a; content-box 内容区 默认值…

机器学习之神经结构搜索(Neural Architecture Search,NAS)附代码

概念 神经结构搜索(Neural Architecture Search,NAS)是一种自动化机器学习技术,它旨在通过搜索神经网络的结构空间来找到最优的网络架构,以解决特定的任务。通常,这个搜索过程可以通过强化学习、进化算法、遗传算法或其他优化方法来完成。神经结构搜索的目标是提高神经网…

持续集成交付CICD:HELM 手动完成前端项目应用发布与回滚

目录 一、实验 1.环境 2.K8S master节点部署HELM3 3.K8S master节点安装git 4. Harbor镜像确认 5. HELM 手动完成前端项目应用发布与回滚 6.代码上传到GitLab 二、问题 1.Ingress中 path 的类型有何区别 2. HELM创建项目报错 一、实验 1.环境 &#xff08;1&#x…

智能优化算法应用:基于野狗算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于野狗算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于野狗算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.野狗算法4.实验参数设定5.算法结果6.参考文献7.MA…

APP测试要点有哪些?本文已经给你梳理好了!

我们日常购物、旅游、支付等活动都离不开手机&#xff0c;由此衍生了很多APP。 比如每天使用频率非常高的微信、支付宝、微博、抖音、王者荣耀等等。 APP测试主要进行功能测试、性能测试、自动化测试、安全性测试、兼容性测试、专项测试。 01 APP测试流程 APP测试流程与web…

NLP论文阅读记录 - AAAI-23 | 01 Cogito Ergo Summ:通过语义解析图和一致性奖励对生物医学论文进行抽象总结

文章目录 前言0、论文摘要一、Introduction1.1目标问题1.2相关的尝试1.3本文贡献 二.相关工作2.1抽象概括2.2图增强摘要2.3 抽象概括的强化学习 三.本文方法COGITOERGOSUMM 框架3.1 问题陈述3.2 图表构建**事件图****AMR 图****图合并和重新连接**Model文本编码器图编码器解码器…

机器学习--线性回归

目录 监督学习算法 线性回归 损失函数 梯度下降 目标函数 更新参数 批量梯度下降 随机梯度下降 小批量梯度下降法 数据预处理 特征标准化 正弦函数特征 多项式特征的函数 数据预处理步骤 线性回归代码实现 初始化步骤 实现梯度下降优化模块 损失与预测模块 …

在Linux Docker中部署RStudio Server,实现高效远程访问

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;网络奇遇记、Cpolar杂谈 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;前言一. 安装RStudio Server二. 本地访问三. Linux 安装cpolar四. 配置RStudio serv…

图像卷积操作

目录 一、互相关运算 二、卷积层 三、图像中目标的边缘检测 四、学习卷积核 五、特征映射和感受野 一、互相关运算 严格来说&#xff0c;卷积层是个错误的叫法&#xff0c;因为它所表达的运算其实是互相关运算&#xff08;cross-correlation&#xff09;&#xff0c;而不是…