• 面向过程
    1.1 面向过程特点
    1.2 通俗解释:煮方便面
    1.3 面向过程实现代码
    1.4 特点总结

  • 面向对象
    2.1 面向对象特点
    2.2 通俗解释:对象协作思维
    2.3 面向对象实现代码
    2.4 特点总结

  • 面向对象和面向过程总结

  • C++ 面向对象介绍
    4.1 面向对象三大基本特征

    • 封装(Encapsulation)

    • 继承(Inheritance)

    • 多态(Polymorphism)
      4.2 三大特征的通俗解释

  • C++ 类与对象初识
    5.1 类的定义
    5.2 类的对象
    5.3 类的访问控制与封装
    5.4 类的成员函数

    • 声明与实现都放在 .h 文件中

    • 声明放在 .h 文件,定义放在 .cpp 文件

  • 总结

面向过程和面向对象

面向过程

核心是强调过程/步骤,程序就是一系列函数和语句的组合,把问题分解为一系列步骤(函数),数据在函数间传递

面向过程特点:

  1. 以函数为中心: 函数是主要的组织单位
  2. 数据与函数分离:数据结构独立存在,函数对数据进行操作
  3. 自顶向下设计:先规划整体流程,再逐步细化
  4. 适合小型程序:逻辑简单,编写快速

面向对象

强调对象,程序由对象组成,对象封装了数据(属性)和行为(方法),面向对象是通过模拟现实世界中的事物和关系来解决问题

面向对象特点:

  1. 以对象为中心: 对象是基本单位
  2. 数据与方法封装:对象内部隐藏实现细节,通过接口与外部交互
  3. 三大特性:封装(Encapsulation)、继承(Inheritance)、多态(Polymorphism
  4. 适合大型复杂系统:可扩展,可复用,可维护

通俗解释

煮方便面为例对比面向过程面向对象

面向过程:
思维方式: 一步步按流程来做

  1. 烧开水
  2. 打开调料包倒进碗里
  3. 把面饼放进开水煮熟
  4. 把面和汤放进碗里
  5. 等待一下,就可以吃了
    这里每个动作就是一个"函数/步骤",整个煮面过程就是把这些步骤顺序执行

面向过程实现代码:

#include <iostream>
#include <thread>
#include <chrono> // 用于等待
using namespace std;
// 步骤 1: 烧开水
void boilWater() {cout << "正在烧开水..." << endl;this_thread::sleep_for(chrono::seconds(1));cout << "水已经烧开了。" << endl;
}
// 步骤 2: 打开调料包倒进碗里
void addSeasoning() {cout << "打开调料包,倒进碗里。" << endl;
}
// 步骤 3: 把面饼放进开水煮熟
void cookNoodles() {cout << "把面饼放进开水里煮..." << endl;this_thread::sleep_for(chrono::seconds(2));cout << "面已经煮熟了。" << endl;
}
// 步骤 4: 把面和汤放进碗里
void serveNoodles() {cout << "把面和汤一起倒进碗里。" << endl;
}
// 步骤 5: 等待一下,就可以吃了
void waitAndEat() {cout << "等待冷却一下..." << endl;this_thread::sleep_for(chrono::seconds(1));cout << "可以开动啦!" << endl;
}
int main() {boilWater();addSeasoning();cookNoodles();serveNoodles();waitAndEat();return 0;
}

特点:

  • 以"过程为主"
  • 如果要换成"煮饺子",要重新写一套步骤
  • 不强调"面"本身的特性,只关心动作顺序


    面向对象:
    思维方式:把事物抽象成对象
  • 有一个水壶对象,它有属性: 容量,水温,有方法: 烧水()
  • 有一个面对象,它有属性:面饼大小,口味,有方法: 煮()
  • 有一个调料对象,它有方法: 添加()
  • 有一个人对象,他只需要调用
person.做饭(面, 水壶, 调料)

只要调用对象的方法,就能完成煮面

这里强调的是对象之间的协作,而不是具体的步骤细节

面向对象实现代码

#include <iostream>
#include <thread>
#include <chrono>using namespace std;// 水壶对象
class Kettle {
public:void boilWater() {cout << "水壶开始烧水..." << endl;this_thread::sleep_for(chrono::seconds(1));cout << "水壶烧开了水。" << endl;}
};// 调料对象
class Seasoning {
public:void addToBowl() {cout << "调料包已倒入碗中。" << endl;}
};// 面对象
class Noodle {
public:void cook() {cout << "面饼放进开水中煮..." << endl;this_thread::sleep_for(chrono::seconds(2));cout << "面已经煮熟了。" << endl;}
};// 人对象
class Person {
public:void cookNoodles(Kettle& kettle, Seasoning& seasoning, Noodle& noodle) {kettle.boilWater();   // 调用水壶的方法seasoning.addToBowl(); // 调用调料的方法noodle.cook();        // 调用面的煮方法cout << "把面和汤一起倒进碗里。" << endl;cout << "等待冷却一下..." << endl;this_thread::sleep_for(chrono::seconds(1));cout << "可以开动啦!" << endl;}
};int main() {Kettle kettle;Seasoning seasoning;Noodle noodle;Person person;person.cookNoodles(kettle, seasoning, noodle);return 0;
}

特点:

  • 以"对象"为主
  • 如果换成"煮饺子",只需要定义一个饺子对象,人对象调用==做饭(饺子,水壶,调料)==就行
  • 强调复用性和扩展性

面向对象和面向过程总结

面向过程是一种以步骤和函数为核心的编程思想,强调“怎么做”,适合小型、逻辑清晰的程序;而面向对象则以对象及其属性和行为为核心,强调“谁来做”,通过封装、继承和多态实现更好的复用与扩展,适合构建大型、复杂、可维护的系统

c++面向对象介绍

C++ 面向对象(OOP, Object-Oriented Programming)是一种程序设计思想,它将现实世界中的事物抽象成“对象”,通过对象之间的交互来完成程序功能。C++ 在 C 的基础上引入了类(class)和对象(object),使得它既支持面向过程(POP),又支持面向对象。

面向对象三大基本特征

C++ 面向对象的核心特性是 封装、继承、多态

  • 封装
    • 把数据(成员变量)和操作数据的函数(成员函数)封装到类中,形成一个整体。
    • 提供 public / private / protected 访问权限,保证数据安全。
    • 举例:银行卡类,余额是私有的,必须通过 取钱()存钱() 方法来访问。
  • 继承
    • 一个类可以继承另一个类的成员(变量和方法)。
    • 允许代码复用,同时可以扩展功能
    • 举例:学生类 继承 人类,就自动拥有了姓名、年龄属性,还可以扩展为学号、成绩。
  • 多态
    • 相同的操作针对不同对象有不同的表现。
    • 分为 静态多态(函数重载、运算符重载)和 动态多态(虚函数 + 基类指针/引用)。
    • 举例:动物 类有一个 speak() 方法, 调用时输出“汪汪”, 调用时输出“喵喵”。

面向对象三大基本特征的通俗解释

封装就像一个自动售货机,你只需要按按钮投币(调用接口),不需要知道机器内部怎么找零,怎么调货(内部实现被隐藏),在编程里,封装就是把数据和操作打包起来,只暴露需要的部分可以保护数据安全,别人不能乱动


继承就像儿子继承父亲的基因和财产,儿子天生就有父亲的特征(属性和方法,但儿子还可以有自己独特的技能(扩展功能)。在编程里,继承就是子类自动拥有父类的代码,可以复用和扩展可以不用重复造轮子


多态就像大家就像大家都能说“打招呼”,但表达方式不同:

  • 中国人说:“你好!”
  • 美国人说:“Hello!”
  • 日本人说:“こんにちは!”
    虽然动作一样,但不同人表现不同,在编程里,多态就是同一个接口,不同对象有不同的实现可以让代码更灵活

C++类与对象初识

  • 类(class):定义了一类事物的属性和行为,是一种模板/蓝图
  • 对象(object):类的实例,是实际存在的个体

类的定义

类的定义由关键字class开始,并通过{}包裹类的内容,类的成员包括:

  • 数据成员:用于存储类对象的状态(属性)
  • 成员函数:描述对象可以执行的行为(操作)
class Car {
private:string model;  // 数据成员int year;      // 数据成员
public:// 成员函数:用来设置车辆的型号void setModel(string m);// 成员函数:用来获取车辆的型号string getModel();// 成员函数:用来设置车辆的年份void setYear(int y);// 成员函数:用来获取车辆的年份int getYear();
};

类的对象

类定义之后,我们可以创建该类的对象,类的对象即是类的实例化

int main() {Car myCar;               // 创建一个名为 myCar 的 Car 类型对象myCar.setModel("BMW");    // 设置 myCar 的 modelmyCar.setYear(2021);      // 设置 myCar 的 yearcout << myCar.getModel() << " " << myCar.getYear() << endl;  // 输出:BMW 2021return 0;
}

类的访问控制与封装

想象一下你在银行开了一个账户,账户里有余额,你或者其他人都不能跑到银行的数据库去修改余额,比如改成999999999999,这样做明显是不合理的,银行只给你两个合法的窗口:存钱和取钱,这样设计的好处有:你的余额不会被随便修改,安全性高,你只需要关心“怎么存取钱”,而不用操心银行内部如何记账,银行后台可以随时升级换系统,对客户来说使用方式不变,这其实就是封装与访问控制的真实写照

为了保护数据安全,简化使用,方便维护,体现面向对象思想,C++要对类进行访问控制与封装。

在C++中,类的成员默认是私有的,也就是说,外部无法直接访问类的成员变量,如果希望外部能够访问成员,必须通过公共接口来提供访问权限

访问权限

  • public:公有成员,类外部可以访问
  • private:私有成员,类外部无法直接访问
  • protected:保护成员,类外部无法直接访问,但可以被派生类访问
class Car {
private:string model;  // 私有成员变量
public:void setModel(string m) { model = m; }  // 公有成员函数string getModel() { return model; }     // 公有成员函数
};

类的成员函数

类成员函数的定义方式

在C++中,类中的成员函数可以通过两种方式进行定义:

  1. 将类的声明与实现都放在一个 .h 文件中

  2. 将类的声明放在 .h 文件中,将实现放在 .cpp 文件中

我们首先来看第一种方式:

将声明和定义都放在 .h 文件中的方式

这种做法并不推荐,主要有以下几个问题:

  1. 可能导致重复定义:如果 .h 文件被多个源文件包含,就会在每个源文件中生成一份函数的实现,导致链接时发生重复定义错误。

  2. 编译速度变慢:每个源文件都会重新编译类的实现部分,导致编译时间增加。

  3. 模块边界不清晰:将实现放在头文件中,会让代码的结构变得不清晰,维护起来比较困难。

例如,下面是一个简单的例子:

#pragma once
#include <iostream>
#include <string>class Person {std::string _name;std::string _sex;int _age;
public:Person(std::string name, std::string sex, int age) {_name = name;_sex = sex;_age = age;}void show();  // 函数声明
};// 这里是函数定义,直接放在了头文件中
void Person::show() {std::cout << "姓名:" << _name << std::endl;std::cout << "性别:" << _sex << std::endl;std::cout << "年龄:" << _age << std::endl;
}
#include"Person.h"
int main()
{Person p("张三", "男", 20);p.show();
}

然后在另一个 .cpp 文件中:

#include"Person.h"
void test()
{Person p1("张三", "男", 20);p1.show();
}

上述代码不能成功编译,原因是头文件中的函数定义会在每个包含该头文件的 .cpp 文件中生成一份,最终会导致链接时出现重复定义的错误。

重复定义错误示意图

即使没有发生重复定义,编译速度也会因为每个源文件都需要重新编译函数实现部分而变慢。此外,这种做法会导致模块之间的边界不清晰,代码的结构会变得不容易维护。

将类的声明放在 .h 文件中,将实现放在 .cpp 文件中

将类的声明放在.h文件中,实现放在.cpp文件中,是C++开发中的标准做法,不仅解决了上面重复定义的问题还带来了提升编译效率,增强代码的模块化、封装性可维护性,同时也提高了 代码的可读性可重用性 的好处。这种做法是C++中的标准实践

总结

在本篇博客中,我们对比了面向过程(Procedural Programming)与面向对象(Object-Oriented Programming)两种常见的编程思想,并通过通俗易懂的示例进行了讲解。

  • 面向过程强调程序的执行顺序,适用于逻辑简单、功能明确的小型程序。它通过将问题拆解为一系列步骤或函数,着重于“怎么做”。

  • 面向对象则通过模拟现实世界中的对象与关系,将数据与操作封装到对象中,强调“谁来做”。它通过封装、继承和多态这三大特性,提升了代码的复用性、扩展性和可维护性,适合大型、复杂的系统设计。

通过代码示例,我们展示了两种思想在实际编程中的应用。面向过程的设计直接关注操作步骤,灵活快捷,但扩展性差;而面向对象则通过抽象和封装将数据与行为结合,便于扩展与维护。不同的场景下,我们可以根据程序的复杂度和需求来选择合适的设计思想。
在学习和使用面向对象时,我们还讨论了类与对象的基本概念、封装与访问控制的实现方式,了解了如何设计和组织代码,使其更具可读性、可维护性与可扩展性。
最终,面向过程面向对象并不是对立的,二者各有优劣。在实际开发中,我们往往会根据具体需求综合使用它们,从而达到最佳的开发效果。掌握这两种编程思想,并在合适的场景中应用,将使我们成为更高效、更有创造力的软件开发者。

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

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

相关文章

C++ Int128 —— 128位有符号整数类实现剖析

&#x1f9e0; C Int128 —— 128位有符号整数类实现剖析 引用&#xff1a;openppp2/ppp/Int128.h &#x1f3d7;️ 1. 存储结构设计 #mermaid-svg-2JDFsdz6MTbX253D {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-sv…

【C 语言生成指定范围随机数(整数 + 小数):原理、实现与避坑指南】

概述 在 C 语言开发中&#xff0c;生成指定范围的随机数是高频需求&#xff08;如游戏随机道具、数据模拟、测试用例生成等&#xff09;。但很多新手会卡在 “范围控制”“随机数重复”“小数生成” 等问题上。本文结合实战场景&#xff0c;从原理到代码详细讲解如何生成 1100、…

一个简单的langgraph agent系统

本文基于langgraph的预制件 Agent Chat UI和《搭建一个本地langgraph服务》中的本地服务构建一个简单的agent系统。 说明&#xff1a;Agent Chat UI需要nodejs版本18及以上&#xff0c;而nodejs18需要的glibc版本为2.28&#xff0c;本人使用操作系统为ubuntu18.04&#xff0c;g…

通过SSH来推送本地文件夹到Github

配置SSH git使用SSH配置&#xff0c; 初始需要以下三个步骤 使用秘钥生成工具生成rsa秘钥和公钥 将rsa公钥添加到代码托管平台 将rsa秘钥添加到ssh-agent中&#xff0c;为ssh client指定使用的秘钥文件 具体操作如下&#xff1a; 第一步&#xff1a;检查本地主机是否已经存在…

视频转webp批量处理工具哪个好?这里有答案

你是不是也遇到过这样的困扰&#xff1a;手机里存满了精彩的短视频&#xff0c;想做成动图分享到社交媒体&#xff0c;却发现转换后的GIF文件巨大无比&#xff0c;画质还惨不忍睹&#xff1f;要怎么把手机视频转webp&#xff0c;才能既保持高清画质&#xff0c;又能大幅减小文件…

【Fastjson】Fastjson2 在不同 Modules 模块包下,@JSONField name映射无法反序列化的 BUG 及解决

问题&#xff1a;在使用 alibaba fastjson2 做 JSONField 字段名映射时&#xff0c;在同模块包下 Flink Jar 任务正常映射&#xff0c;本地测试正常映射&#xff0c;但是将两个模块包上传至 Flink Cluster 之后&#xff0c;出现反序列化异常&#xff0c;子模块无法反序列化父模…

Go语言基础---数据类型间的故事

Go语言基础—数据类型间的故事 目录 前言基本数据类型 整形字节特殊整形unsafe.Sizeof数字字面量语法浮点型布尔值字符串byte和rune类型 运算符 算术运算符关系运算符逻辑运算符位运算符赋值运算符 前言 Go语言是Google开发的一种静态强类型、编译型语言。Go语言语法与C相近…

dedecms软件等级★号改成图片图标显示的办法

我们在用到dedecms织梦的软件模型&#xff0c;在调用软件星级的时候&#xff0c;要把默认的星号改为图片&#xff0c;这个要怎么操作呢&#xff1f;1、软件模型管理里面-字段管理-字段配置softrankislink一行改为&#xff1a;<field:softrank itemname软件等级 typeint isnu…

windows下安装claude code+国产大模型glm4.5接入(无需科学上网)

下载安装node.js https://nodejs.org/en/download 安装版.msi 直接下载安装即可 免安装版.zip 1.解压下载的压缩包 2.创建数据缓存存储目录cache和全局安装工具目录global 3.配置环境变量 【我的电脑】右键选中【属性】-> 找到【高级系统设置】-> 右下角【环境变量…

嵌入式 - ARM4

裸机实现LED闪烁一、启动代码1. 异常向量表配置1. .global汇编器指令&#xff0c;全局定义标签_start&#xff0c;作为汇编程序的默认起点2. 配置标签配置标签时可以前置加_ &#xff0c;以便和普通标签或系统标签做区分3. 异常向量表ARM架构规定异常向量表位置固定&#xff0c…

《C++ 108好库》之2 多线程库thread,mutex,condition_variable,this_thread

《C 108好库》之之2 多线程库thread&#xff0c;mutex&#xff0c;condition_variable&#xff0c;this_thread《C 108好库》之2 多线程库thread&#xff0c;mutex&#xff0c;condition_variable&#xff0c;this_threadstd::thread类​​互斥量&#xff08;Mutex&#xff09;…

Android系统框架知识系列(二十):专题延伸:JVM vs ART/Dalvik - Android运行时演进深度解析

​关键词​&#xff1a;运行时优化、AOT编译、JIT编译、内存管理、电池效率、性能分析一、Android运行时演进背景1. 移动环境的特殊挑战Android运行时环境的演进源于移动设备的独特限制&#xff1a;​移动设备约束条件​&#xff1a;​有限的内存资源​&#xff1a;早期设备仅1…

ubuntu 22 安装轻量级桌面Xfce并使用xrdp远程桌面连接

1.安装Xfce:sudo apt install xubuntu-desktop -y2.安装xrdp:sudo apt install xrdp -y3.配置xrdp&#xff0c;nano /etc/xrdp/xrdp.ini:[Globals] ... port3389 ; 远程连接端口&#xff0c;默认是3389&#xff0c;可以改成自己喜欢的端口... ; ; Session types ;; Some sess…

【Flask】测试平台开发,数据看板开发-第二十一篇

概述&#xff1a;在前面我们已经实现了我们的产品创建管理&#xff0c;应用管理管理&#xff0c;需求提测管理但是每周提测了多少需求&#xff0c;创建了哪些产品&#xff0c;我们是不是看着不是很直观&#xff0c;接下来我们就需要开发一个数据看板功能&#xff0c;实现能够看…

我是程序员,不是程序猿:请别把我当猴耍——拒绝被低估,用专业赢得尊重

摘要 本文旨在深度剖析“程序员”与“程序猿”一字之差背后所反映的职业尊严与身份认同问题。我们生活在一个技术驱动的时代&#xff0c;但对技术创造者的认知却常常被“程序猿”、“码农”等标签简单化、甚至矮化。本文将从正名开始&#xff0c;辨析“程序员”的专业内涵&…

C++中vector删除操作的安全隐患与最佳实践

std::vector 是C标准模板库&#xff08;STL&#xff09;中最常用的动态数组容器&#xff0c;提供了高效的随机访问和动态扩容能力。然而&#xff0c;其删除操作如果使用不当&#xff0c;会引入严重的安全隐患&#xff0c;包括未定义行为、内存泄漏和数据竞争等问题。本文将深入…

Unix/Linux 系统中的 `writev` 系统调用

<摘要> 本文对 Unix/Linux 系统中的 writev 系统调用进行了全面深入的解析。内容涵盖了其产生的背景&#xff08;从传统 write 的局限性到分散/聚集 I/O 概念的引入&#xff09;、核心概念&#xff08;如 struct iovec、系统调用流程&#xff09;。重点剖析了其设计意图&…

深入理解 Android targetSdkVersion:从 Google Play 政策到依赖冲突

深入理解 Android targetSdkVersion&#xff1a;从 Google Play 政策到依赖冲突 作为 Android 开发者&#xff0c;你很可能在 Android Studio 中见过这条提示&#xff1a;Google Play requires that apps target API level 33 or higher。它像一个尽职的提醒者&#xff0c;时常…

灰匣(GrayBox)1.0.0 发布【提升系统权限APP】

灰匣是一个提升系统权限的工具&#xff0c;可以配合Root、三方软件&#xff08;Shizuku&#xff09;以及【设备管理员】&#xff08;设备所有者&#xff09;实现一些高级功能及底层接口&#xff0c;可以自动隔离&#xff08;冻结/禁用&#xff09;不必要的应用&#xff0c;如某…

PAT 1104 Sum of Number Segments

这一题的大意就是找一个数组中的所有子数组&#xff0c;它们的累加和为多少&#xff0c; 题目上给出的数据范围是O(n^5)那么只能遍历一次&#xff0c;不能用暴力的方法求出。 看到这一题我有两个思路&#xff1a; 1.试图用双指针和滑动窗口来把O&#xff08;n^2)的时间复杂度降…