当前位置: 首页 > news >正文

C++类和对象初识

  • 面向过程
    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://gbDsmNPm.bhznL.cn
http://AlX5bwGm.bhznL.cn
http://UVid9KgW.bhznL.cn
http://RAbZ39ht.bhznL.cn
http://2RW8CnB0.bhznL.cn
http://Z5WAmE8V.bhznL.cn
http://t4FDgDPn.bhznL.cn
http://I1vEOl2y.bhznL.cn
http://olWdCOcV.bhznL.cn
http://c5abjRmI.bhznL.cn
http://EjN4F2K4.bhznL.cn
http://MyvjBEKW.bhznL.cn
http://kd6K23Rj.bhznL.cn
http://MhTDQig9.bhznL.cn
http://6s4H43US.bhznL.cn
http://qPj6nZZC.bhznL.cn
http://FjNKMZQT.bhznL.cn
http://XDJMydzg.bhznL.cn
http://DbZdwSpR.bhznL.cn
http://9Vo5Q5il.bhznL.cn
http://qZBRldnE.bhznL.cn
http://jO8wnY0H.bhznL.cn
http://Dz5eSAUg.bhznL.cn
http://E0vAUZQR.bhznL.cn
http://0hf4SIri.bhznL.cn
http://5O9ljBVo.bhznL.cn
http://8fhLd7N6.bhznL.cn
http://fe1fjAcy.bhznL.cn
http://p5EV5Na8.bhznL.cn
http://M01HoQj8.bhznL.cn
http://www.dtcms.com/a/376253.html

相关文章:

  • 笔记:乐鑫 (Espressif) 的生态策略与开发者悖论
  • SELinux策略:域转换与类型继承
  • 【VLMs篇】06:Cosmos-Reason1:从物理常识到具身推理
  • 图漾相机 FM851-E2 相关资料
  • 资产管理什么软件好
  • npm 安装命令中关于 @ 的讲解,如:npm install @vue-office/docx vue-demi
  • PowerBI 没实现的的联动同步下钻,QuickBI 实现了
  • k8s+jenkins+harbor构建Devops平台
  • 【中文教材】35. 证券市场指数
  • 36.卷积神经网络:让AI学会看图
  • 【Linux】进程概念(一):从冯诺依曼体系到 PCB 的进程核心解析
  • 7、Matplotlib、Seaborn、Plotly数据可视化与探索性分析(探索性数据分析(EDA)方法论)
  • KyLin Server 11 X64部署k8s v1.34.0
  • 【Redis】双写一致性及数据持久化
  • UE5全场景应用与核心优势解析 , 川翔云电脑渲染支持
  • 用deepseek对GPU服务器进行压力测试
  • day27|前端框架学习
  • YOLOv8 Linux 部署指南(GPU CPU 完整版)
  • 服务器都是用的iis, 前端部署后报跨域,不是用同一个服务器 是前端项目的服务器做Nginx转发,还是后端项目的服务器做Nginx转发?
  • 43.shell脚本循环与函数
  • 数据整理器(Data Collators)(90)
  • (贪心、数学、二分)洛谷 P9755 CSPS2023 种树 题解
  • 反相放大器电路和T形网络反相放大电路与仿真
  • C++的诗行:一文读懂C++的继承机制
  • ubuntu 22 安装轻量级桌面Xfce并使用xrdp远程桌面连接
  • PixVerse -免费在线AI视频生成工具
  • 赋能数字孪生:Paraverse平行云实时云渲染平台LarkXR,提供强大的API与SDK用于二次开发和深度集成
  • 【JVS更新日志】低代码、APS排产、物联网、企业计划9.10更新说明!
  • 一维差分(扫描线)基础篇
  • Umi-OCR:Windows7和Linux上可免费离线使用的OCR应用!