C++奇迹之旅:我与类和对象相遇

请添加图片描述

文章目录

  • 📝面向过程和面向对象初步认识
  • 🌠 类
    • 🌉类的引入
    • 🌉类的定义
  • 🌠类的访问限定符
    • 🌠访问限定符
  • 🌠类的两种定义方式
    • 🌉封装
  • 🚩总结


📝面向过程和面向对象初步认识

C语言是一种面向过程的编程语言,主要关注于如何实现特定的任务或功能。在面向过程编程里**:程序是由一系列步骤或过程组成的,每个步骤都有明确的输入和输出**。数据和操作数据的函数是分开的,数据结构和算法是独立的。代码结构是线性的,更关于"how"而不是"what"。适合于一些简单的、线性的、需要快速实现的程序。

C++是一种面向对象的编程语言,它引入了类、对象、继承、多态等面向对象的概念。在面向对象编程里:关注于如何组织和封装数据和功能程序是由相互交互的对象组成的,每个对象都有自己的数据和方法数据和操作数据的方法是封装在类中的,形成了对象。代码结构是模块化的,更关注于"what"而不是"how"。支持继承和多态等特性,可以实现代码的重用和扩展。适合于一些复杂的、需要良好的代码组织和可维护性的程序。

我们举个例子来更透彻的理解两个过程

比如我们熟悉的PPT制作:

  1. 制作 PPT (面向过程)

面向过程的做法是: 首先确定主题,然后设计版式,接下来添加内容,最后调整格式。每个步骤都是独立的。这种方式更关注于 PPT 制作过程中需要执行的具体步骤。

  1. 幻灯片演示系统 (面向对象)

面向对象的做法:将 PPT 制作过程封装成一个 “幻灯片演示” 类,它包含了页面、文本、图像、动画等属性,以及添加内容、设计版式、调整格式等方法。在制作 PPT 时,我们可以创建不同的幻灯片对象,每个对象都有自己的特点和功能。这种方式更关注于幻灯片这个整体对象,以及它的属性和行为。

因此,比较可以得出:

  • 面向过程:关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。
  • 面向对象:关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成

在此,我们可以初步了解代码里C语言怎么实现面向过程的和C++语言怎么面向对象的:

  1. 我们定义了一个 calculate_circle_area 函数,它接受圆的半径作为参数,计算并返回圆的面积,函数内部使用了 PI 宏定义常量,并使用公式计算面积,
#include <stdio.h>
#define PI 3.14159double calculate_circle_area(double radius) 
{return PI * radius * radius;
}int main() 
{double radius = 5.0;double result = calculate_circle_area(radius);printf("The area of the circle with radius %.2f is %.2f\n", radius, result);return 0;
}
  1. 我们定义了一个 Circle 类,它包含了圆的半径PI 常量作为私有属性。在构造函数 Circle(double r) 中,我们初始化了半径属性。类中还定义了一个 calculateArea 方法,用于计算圆的面积。在 main 函数中,我们创建了一个 Circle 对象,并调用它的 calculateArea 方法来获得结果。
#include <iostream>class Circle 
{
private:double radius;const double PI = 3.14159;public:Circle(double r) : radius(r) {}double calculateArea() {return PI * radius * radius;}
};int main() 
{Circle circle(5.0);double result = circle.calculateArea();std::cout << "The area of the circle with radius " << circle.radius << " is " << result << std::endl;return 0;
}

可以看到,C 语言的面向过程实现,是定义一个函数来计算圆的面积。而 C++ 的面向对象实现则将数据和方法封装在一个 Circle 类中,体现了面向对象的特点。

从这个例子可以看出,面向过程的实现更加直接和简单,关注于如何计算圆的面积。而面向对象的实现则将数据和方法封装在一个 Circle 类中,更加强调对象的概念和行为。

🌠 类

🌉类的引入

在 C 语言中,结构体只能包含数据成员(变量),不能包含函数。,在C++中,结构体内不仅可以定义变量,也可以定义函数。

// C 语言中的栈实现
struct Stack
{int data[MAX_SIZE];int top;
};void push(struct Stack* s, int value) 
{// 实现 push 操作
}int pop(struct Stack* s) 
{// 实现 pop 操作
}

C语言方式实现的栈,结构体中只能定义变量,不能包含函数。
C++升级struct升级成了类,类里面可以定义函数,struct名称就可以代表类型
C++兼容C中struct的用法

// C++ 中的栈实现
struct Stack
{int data[MAX_SIZE];int top;void push(int value) {// 实现 push 操作}int pop() {// 实现 pop 操作}
};

🌉类的定义

class className
{
// 类体:由成员函数和成员变量组成
};  // 一定要注意后面的分号

class为定义类的关键字,ClassName为类的名字,{}中为类的主体,注意类定义结束时后面分号不能省略

类体中内容称为类的成员:类中的变量称为类的属性成员变量; 类中的函数称为类的方法或者成员函数。

我们定义一个学生类:姓名,性别,年龄。

class student
{int name;int sex;int age;
};

在定义成员变量时,为了避免与函数参数名称混淆,通常会在成员变量前加上下划线_作为前缀。这样可以很方便地区分成员变量和函数参数。

class Date
{void Init(int year, int month, int day){_year = year;_month = month;_day = day;}int _year; int _month;int _day;
};
class Date
{void Init(int year, int month, int day){_year = year;_month = month;_day = day;}int _year;int _month;int _day;
};int main()
{Date d;d.Init(2024, 4, 8);return 0;
}

在这个例子中,我们将成员变量year、month和day分别修改为_year、_month和_day。这样在Init()函数中,就可以很清楚地区分函数参数和成员变量。

然后我们运行起来,会发现报了错:“Date::Init”: 无法访问 private 成员(在“Date”类中声明)
在这里插入图片描述
这是为什么呢?这涉及到了类的访问限定符及封装,class默认访问限定符是private,所以不能直接访问,为了能在类外直接访问,因此我们可以使用public访问限定符:

class Date
{
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}int _year;int _month;int _day;
};int main()
{Date d;d.Init(2024, 4, 8);return 0;
}

🌠类的访问限定符

🌠访问限定符

C++实现封装的方式:用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用

C++ 中,访问限定符用于控制类成员的可访问性。主要有以下三种访问限定符:publicprotectedprivate

  1. public:被声明为 public 的成员可以被类的任何部分以及类的外部访问。
class MyClass 
{
public:// public 成员函数void publicFunction() {std::cout << _publicMember << std::endl;}// public 成员变量int _publicMember = 3;
};
  1. private:被声明为 private 的成员只能被类的成员函数访问,类的外部无法访问。
class MyClass 
{
protected:// protected 成员函数void protectedFunction() {std::cout << _protectedMember << std::endl;}// protected 成员变量int _protectedMember = 2;};
  1. protected:被声明为 protected 的成员可以被类的成员函数和派生类的成员函数访问,但类的外部无法访问。
class MyClass 
{
private:// private 成员函数void privateFunction() {std::cout << _privateMember << std::endl;}// private 成员变量int _privateMember = 1;
};

在这里插入图片描述
三个访问限定符结合示例:

class MyClass 
{
public:// public 成员函数void publicFunction() {// 可以访问 public 和 protected 成员std::cout << _publicMember << std::endl;std::cout << _protectedMember << std::endl;// 不能访问 private 成员// std::cout << _privateMember << std::endl;}protected:// protected 成员函数void protectedFunction() {// 可以访问 public、protected 和 private 成员std::cout << _publicMember << std::endl;std::cout << _protectedMember << std::endl;std::cout << _privateMember << std::endl;}private:// private 成员函数void privateFunction() {// 可以访问 public、protected 和 private 成员std::cout << _publicMember << std::endl;std::cout << _protectedMember << std::endl;std::cout << _privateMember << std::endl;}// private 成员变量int _privateMember = 1;// protected 成员变量int _protectedMember = 2;// public 成员变量int _publicMember = 3;
};

【访问限定符说明】

  1. public修饰的成员在类外可以直接被访问
  2. protectedprivate修饰的成员在类外不能直接被访问(此处protected和>private是类似的)
  3. 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
  4. 如果后面没有访问限定符,作用域就到 } 即类结束。
  5. class的默认访问权限为privatestructpublic(因为struct要兼容C)
    注意:访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别

【面试题】
问题:C++structclass的区别是什么?
解答:C++需要兼容C语言,所以C++struct可以当成结构体使用。另外C++中struct还可以用来定义类。和class定义类是一样的,区别是struct定义的类默认访问权限是publicclass定义的类默认访问权限是private。注意:在继承和模板参数列表位置,structclass也有区别,后序给大家介绍。

🌠类的两种定义方式

  1. 声明和定义全部放在类体中,需注意:成员函数如果在中定义,编译器可能会将其当成内联函数处理。
class Rectangle 
{
public:Rectangle(int width, int height) : width(width), height(height) {}int getArea() {return width * height;}int getPerimeter() {return 2 * (width + height);}private:int width;int height;
};

在这个例子中,Rectangle 类的构造函数和两个成员函数 getArea() 和getPerimeter() 都直接在类体中定义。

  1. 声明和定义分离:
    类声明放在.h文件中,成员函数定义放在.cpp文件中,注意:成员函数名前需要加类名::
    .h文件
class Rectangle 
{
public:Rectangle(int width, int height);int getArea();int getPerimeter();private:int width;int height;
};

.cpp文件

Rectangle::Rectangle(int width, int height) : width(width), height(height) {}int Rectangle::getArea() 
{return width * height;
}int Rectangle::getPerimeter() 
{return 2 * (width + height);
}

这里需要特别注意一下:声明和定义分离时,成员函数名前需要加类名::,这是因为编译器如果没有指定作用域时,会在全局作用域和局部作用域找。类自己定义了一个作用域,在类体外定义类成员函数时,需要用域作用域操作符::指定哪个类域。

如果没有加指定类体域,将会出现以下报错
在这里插入图片描述
修改后指定类域即可修复:
在这里插入图片描述

🌉封装

面向对象的三大特性:封装、继承、多态
封装是面向对象编程的重要思想,它通过隐藏内部实现细节,提供标准化的接口,实现了数据的安全性和系统的可维护性,是面向对象编程的基础。
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。

**封装本质上是一种管理,让用户更方便使用类。**比如:对于电脑这样一个复杂的设备,提供给用户的就只有开关机键、通过键盘输入,显示器,USB插孔等,让用户和计算机进行交互,完成日常事务。但实际上电脑真正工作的却是CPU、显卡、内存等一些硬件元件。

在这里插入图片描述

对于计算机使用者而言,不用关心内部核心部件,比如主板上线路是如何布局的,CPU内部是如何设计的等,用户只需要知道,怎么开机、怎么通过键盘和鼠标与计算机进行交互即可。因此计算机厂商在出厂时,在外部套上壳子,将内部实现细节隐藏起来,仅仅对外提供开关机、鼠标以及键盘插孔等,让用户可以与计算机进行交互即可。

在C++语言中实现封装,可以通过类将数据以及操作数据的方法进行有机结合,通过访问权限来隐藏对象内部实现细节,控制哪些方法可以在类外部直接被使用。


🚩总结

请添加图片描述

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

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

相关文章

spring cloud gateway openfeign 联合使用产生死锁问题

spring cloud gateway openfeign 联合使用产生死锁问题&#xff0c;应用启动的时候阻塞卡住。 spring.cloud 版本如下 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><vers…

Docker-compose部署 gitlab-server

Gitlab部署文档 1、配置环境变量 export GITLAB_HOME/srv/gitlab2、创建docker-compose.yml文件 修改http端口需要同步修改external_url修改ssh端口需要同步修改gitlab_rails[‘gitlab_shell_ssh_port’]volumes&#xff1a;容器数据的持久化存储&#xff0c;强烈推荐。除非你…

arm-none-eabi-addr2line和arm-none-eabi-objdump使用笔记

1. arm-none-eabi-addr2line arm-none-eabi-addr2line -ife ./nuttx/vela_ap.elf 0x0c177186arm-none-eabi-addr2line 是一个用于将地址转换为文件名和行号的工具&#xff0c;用于在嵌入式系统中调试程序时定位代码位置。命令的一般格式是&#xff1a; arm-none-eabi-addr2li…

国际数字影像产业园以数字影像技术,重构文创生活

国际数字影像产业园区&#xff0c;作为树莓集团与成都市金牛区人民政府合作的重点项目&#xff0c;于2023年3月正式在金牛区落地生根。这一园区不仅是第五代产业园区的代表&#xff0c;更是数字影像相关产业服务的特色园区&#xff0c;其独特的定位和宏大的愿景“以数字影像技术…

centos安装nvidia驱动(附各种问题)

一准备 1.1 看开显卡型号 1、Linux查看显卡信息:(ps:若找不到lspci命令,可以安装 yum install pciutils) lspci | grep -i vga 2、使用nvidia GPU可以: lspci | grep -i nvidia 3、查看显卡驱动 cat /proc/driver/nvidia/version 1.2 安装环境依赖 yum install kernel-d…

达梦关键字(如:XML,EXCHANGE,DOMAIN,link等)配置忽略

背景&#xff1a;在使用达梦数据库时&#xff0c;查询SQL中涉及XML,EXCHANGE,DOMAIN,link字段&#xff0c;在达梦中是关键字&#xff0c;SQL报关键词不能使用的错误。 解决办法&#xff1a; 配置达梦安装文件E:\MyJava\dmdbms\data\DAMENG\dm.ini 忽略这些关键词&#xff0c;…

景联文科技:为AI大模型提供高质海量训练数据

在全球AI浪潮的推动下&#xff0c;大量训练数据已成为AI算法模型发展和演进中的关键一环。 艾瑞咨询数据显示&#xff0c;包括数据采集、数据处理&#xff08;标注&#xff09;、数据存储、数据挖掘等模块在内的AI基础数据服务市场&#xff0c;将在未来数年内持续增长。 预计到…

MySQL典型示例

目录 1.使用环境 2.设计表 3.创建表 4.准备数据 5.查询 1.使用环境 数据库&#xff1a;MySQL 8.0.30 客户端&#xff1a;Navicat 15.0.12 2.设计表 假设我们已经建好了一个名为test的数据库。我们添加如下几个表&#xff1a;教师、课程、学生、班级、成绩。实体联系图设…

跨平台私人ChatGPT应用ChatGPT-Next-Web

什么是 NextChat (ChatGPT Next Web) &#xff1f; NextChat (ChatGPT Next Web) 是可以一键免费部署的跨平台私人 ChatGPT 应用, 支持 GPT3, GPT4 & Gemini Pro 模型。 准备 因为老苏没有 OpenAI Key&#xff0c;所以使用 FreeGPT35 来提供无限免费的 GPT-3.5-Turbo API …

qt调试日志文件生成

系列文章目录 第一章 qt日志文件生成功能 文章目录 系列文章目录前言一、qt日志文件生成功能二、使用步骤1.代码示例2.运行截图 前言 qt有固定的调试日志接口&#xff0c;可以通过终端去打印&#xff0c;但是仅适用在本地去调试&#xff0c;例如想长期放到测试台去检测&#…

MVCC-多版本并发控制

MVCC&#xff08;多版本并发控制&#xff09;简介 在数据库系统中&#xff0c;并发控制是一个非常重要的话题。为了提高系统的并发性能和吞吐量&#xff0c;现代数据库系统通常使用多种技术来实现对数据的安全访问&#xff0c;其中一种重要的技术就是多版本并发控制&#xff0…

springboot设置RestTemplate支持httphttps

1.添加HttpsClientRequestFactory public class HttpsClientRequestFactory extends SimpleClientHttpRequestFactory {Overrideprotected void prepareConnection(HttpURLConnection connection, String httpMethod) {try {if (!(connection instanceof HttpsURLConnection))…

如何给MySQL数据库的所有表统一加上字段

在开发过程中&#xff0c;有时候慢慢的建了很多数据库表&#xff0c;但是后来发现需要统一增加某些字段的时候&#xff0c;可以通过alter语句 ALTER TABLE 表名 ADD 列名 数据类型;比如我要给t_user表增加gmt_create与gmt_modified字段&#xff0c;用作记录新增记录时间与更新…

【机器人】PyBullet四足机器狗仿真

随着科技的迅猛发展&#xff0c;机器人技术正日益成为现实生活中的重要组成部分。而在机器人研究领域&#xff0c;仿真技术的应用扮演着不可或缺的角色。它不仅可以节约大量资源和成本&#xff0c;更为工程师和研究者提供了一个安全、高效的实验平台。在这个博客中&#xff0c;…

hanlp中文分词器(ing...)

目前的工作中需要对文本进行分词分析词性,找出热词,经过一系列的调研感觉hanlp这个库还不错,想先试用看看 介绍 HanLP&#xff08;Han Language Processing&#xff09;是一个由一系列模型与算法组成的NLP工具包&#xff0c;目标是普及自然语言处理在生产环境中的应用。HanLP…

工地安全监测识别摄像机

工地安全监测识别摄像机是一种在建筑工地和施工现场广泛使用的智能监控设备&#xff0c;主要用于监测施工过程中可能出现的安全隐患和违规行为&#xff0c;以确保工地人员和设备的安全。通过高清摄像头、智能算法和远程监控系统的结合&#xff0c;该摄像机可以实时监测工地各个…

node.js 中的require用法 和import的区别

node.js 中的require用法 在Node.js中&#xff0c;require是一个内置的函数&#xff0c;用于在当前模块中加载和缓存其他模块。这是Node.js模块系统的基础&#xff0c;允许你导入第三方库或其他模块文件。这里是一些基本用法和注意事项&#xff1a; 基本用法 导入核心模块&am…

【gitlab】修改默认存放存放目录

流程 共享文件路径是 /mnt/hgfs/project停掉gitlab gitlab-ctl stop修改gitlab的配置文件,找到 vim /etc/gitlab/gitlab.rb找到 git_data_dirs里面的path 换成共享文件路径 # git_data_dirs({ # "default" > { # "path" > "/mnt/hgfs/…

C#设计简单的WinForms多窗口应用程序[示例]

这个程序是一个简单的多窗口应用程序&#xff0c;使用了 Windows 窗体&#xff08;WinForms&#xff09;来创建用户界面。让我们逐步分析它的结构&#xff1a; 1. **命名空间&#xff08;Namespace&#xff09;&#xff1a;** 整个程序位于名为 MultiWindowApp 的命名空间中…

电商社交新零售:创新引领新趋势,变革新零售思维格局-亿发

新零售O2O模式是如何颠覆传统零售商业模式&#xff1f; 传统电商出现瓶颈&#xff1a; 传统电商在发展过程中逐渐出现了瓶颈&#xff0c;主要表现在市场竞争激烈、用户获取成本上升、用户黏性下降等问题。传统电商往往只能通过价格竞争或促销活动来吸引用户&#xff0c;而这种…