六、类和对象

六、类和对象

  • 概念
  • 四大特性
  • 类和对象
    • 类(Class)
    • 对象(Object)
    • 访问修饰符
  • 类的创建和对象的初始化
    • 创建类
    • 初始化对象
  • `class`与`struct` 的区别
  • 类的声明和实现分离
  • `string`
    • 包含头文件
    • 声明和初始化字符串
    • 访问字符串中的字符
    • 修改字符串
    • 字符串连接
    • 字符串长度
    • 字符串比较
    • 查找子字符串
    • 字符串截取
    • 字符串转换
    • 常用函数
      • 构造函数
      • 访问函数
      • 容量函数
      • 修改函数
      • 搜索和查找函数

概念

面向对象(Object Oriented)是一种软件开发方法和程序设计范式,它强调从现实世界的客观存在出发,以对象作为系统的基本构成单位来构造软件系统。

  • 面向对象是一种对现实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后的产物。
  • 它将现实世界中的事物抽象为对象,将事物之间的关系抽象为类、继承等概念。
  • 面向对象是相对于面向过程来讲的,它更贴近事物的自然运行模式,将相关的数据和方法组织为一个整体来看待。
  • 面向过程:就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。
  • 面向对象:是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描述某个事物在整个解决问题的步骤中的行为。

四大特性

面向对象的四大特性(也称为OOP的四大支柱)包括:抽象(Abstraction)、封装(Encapsulation)、继承(Inheritance)和多态(Polymorphism)。

  1. 抽象(Abstraction)
    抽象是指将现实世界中的某一类事物共有的特征抽象出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。通过抽象,我们可以忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。

  2. 封装(Encapsulation)
    封装是把对象的属性和操作结合成一个独立的系统单位,并尽可能隐藏对象的内部细节(属性和方法的实现细节)。封装的主要目的是增强安全性和简化编程,使用者无需了解具体的实现细节,而只是通过外部接口、以特定的访问权限来使用类的成员。

  3. 继承(Inheritance)
    继承是面向对象编程(OOP)实现代码重用的一个重要手段。如果一个类A继承自另一个类B,就把类B叫做类A的父类(超类、基类),类A叫做类B的子类(派生类)。子类可以直接访问父类的非私有的属性和方法,这就是继承的基本思想。通过继承,我们可以基于已存在的类来定义新的类,这样可以大大提高代码的重用性。

  4. 多态(Polymorphism)
    多态是指不同的对象对同一消息做出不同的响应。多态包括参数多态和包含多态。多态性允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说就是用同样的对象引用调用同样的方法但是做了不同的事情。多态性分为编译时的多态性和运行时的多态性。

这四大特性共同构成了面向对象编程的基础,使得代码更加模块化、可重用和可扩展。在软件开发过程中,合理地使用这些特性可以提高开发效率和代码质量。

类和对象

在C++中,类和对象是面向对象编程(OOP)的核心概念。类(Class)是一个用户定义的数据类型,它定义了一个对象的属性和方法(在C++中通常称为成员函数)。对象(Object)是类的实例,它是根据类创建的具体存在。

类(Class)

类定义了对象的蓝图或模板,它指定了对象应有的属性和可以执行的操作。在C++中,类使用class关键字来定义。

对象(Object)

对象是类的实例。你可以使用类来创建对象,并通过这些对象来访问类的成员变量和成员函数。

访问修饰符

在C++中,类的成员(包括成员变量和成员函数)可以有三种访问修饰符:public、protected和private。默认情况下,如果不指定访问修饰符,则成员的访问级别是private。

  • public:成员可以从任何地方被访问。
  • protected:成员可以被其派生类(子类)和同一个包(在C++中,这通常指的是同一个类)中的其他成员访问。
  • private:成员只能被同一个类中的其他成员访问。

类的创建和对象的初始化

在C++中,类的创建是通过class关键字来完成的,而对象的初始化则涉及到类的构造函数。下面是一个详细的例子,说明如何创建类以及如何使用构造函数来初始化对象。

创建类

首先,你需要定义一个类。类定义了对象的属性和方法。以下是一个简单的Rectangle类的例子:

class Rectangle {
private: // 通常,成员变量应声明为私有,以保持封装性
    double width;
    double height;

public: // 公有成员函数可以被类的对象访问
    // 默认构造函数
    Rectangle() : width(0.0), height(0.0) {}

    // 带参数的构造函数
    Rectangle(double w, double h) : width(w), height(h) {}

    // 计算面积的方法
    double area() const { return width * height; }

    // 计算周长的方法
    double perimeter() const { return 2 * (width + height); }

    // 可能的setter和getter方法(如果需要的话)
    void setWidth(double w) { width = w; }
    void setHeight(double h) { height = h; }
    double getWidth() const { return width; }
    double getHeight() const { return height; }
};

在这个例子中,Rectangle类有两个私有成员变量widthheight,以及几个公有成员函数,包括两个构造函数、计算面积和周长的方法,以及可能的setter和getter方法。

初始化对象

要创建一个Rectangle类的对象,你需要使用类的构造函数。构造函数是一种特殊的成员函数,它在创建类的对象时自动调用。以下是如何使用上面的Rectangle类来创建和初始化对象的例子:

int main() {
    // 使用默认构造函数创建一个Rectangle对象,其width和height都初始化为0
    Rectangle rect1;

    // 使用带参数的构造函数创建一个Rectangle对象,并指定width和height的值
    Rectangle rect2(10.0, 5.0);

    // 访问对象的公有成员函数
    std::cout << "Area of rect1: " << rect1.area() << std::endl; // 输出0,因为width和height都是0
    std::cout << "Area of rect2: " << rect2.area() << std::endl; // 输出50

    // 可以通过setter方法修改对象的属性值
    rect2.setWidth(20.0);
    std::cout << "Area of rect2 after modifying width: " << rect2.area() << std::endl; // 输出100

    return 0;
}

在这个例子中,我们首先使用默认构造函数创建了一个Rectangle对象rect1,它的widthheight都被初始化为0。然后,我们使用带参数的构造函数创建了一个Rectangle对象rect2,并指定了width为10.0,height为5.0。接着,我们调用了对象的area()方法来计算并打印面积。最后,我们使用setWidth()方法修改了rect2width属性值,并再次计算并打印了面积。

classstruct 的区别

classstruct在编程中都是用于定义用户自定义数据类型的关键字,但它们之间存在一些显著的区别。

  1. 类型与存储

    • class是引用类型,它在堆中分配空间,栈中保存的是指向该对象的引用。
    • struct是值类型,它在栈中分配空间,并且直接存储数据。
  2. 继承与派生

    • class支持继承,允许一个类继承自另一个类,从而继承其属性和方法。
    • struct不支持继承,它不能被其他structclass继承,也不能从其他类型继承。
  3. 成员访问权限

    • class的成员可以是私有的(private)、保护的(protected)或公有的(public)。
    • struct的成员默认为公有(public),但也可以明确指定为私有或保护。
  4. 构造函数与初始化

    • class的构造器需要显式定义,如果不手动实现构造函数,编译器会报错(除非所有的成员变量都是可选的或有默认值)。
    • struct的构造器是隐式的,编译器会自动生成一个无参数的构造函数,即使成员变量没有初始化,编译器也不会报错。
  5. 内存管理

    • 由于class是引用类型,所以在赋值或作为参数传递时,传递的是引用而非实际对象,这可能导致意外的数据共享和修改。
    • struct作为值类型,在赋值或作为参数传递时,传递的是实际数据的副本,因此修改一个副本不会影响原始数据。
  6. 与接口的关系

    • classstruct都可以实现接口,但如果没有实现接口的方法,class会报错,而struct则不会。
  7. 可空性

    • 在C#等语言中,class类型的变量可以被设置为null,表示没有引用任何对象。
    • struct由于是值类型,不能被设置为null
  8. 性能考虑

    • 由于struct直接在栈上分配内存,并且在传递时复制整个数据,因此在处理大量小数据或需要频繁复制数据时,struct可能具有更好的性能。
    • class由于涉及到堆内存的分配和引用传递,可能在某些情况下导致性能下降。
  9. 设计哲学

    • class通常用于表示具有复杂行为的数据结构,如对象、集合等。
    • struct通常用于表示简单的数据结构,如点、向量、颜色等,这些数据结构主要关注数据的表示和存储,而不涉及复杂的行为。

综上所述,classstruct在类型、存储、继承、成员访问权限、构造函数、内存管理、与接口的关系、可空性、性能和设计哲学等方面存在显著的区别。在选择使用class还是struct时,应根据具体的需求和场景进行权衡。

类的声明和实现分离

在C++中,类的声明(也称为类的定义)和类的实现(也称为成员函数的定义)通常被分离开来。这是为了保持代码的组织和清晰性,使得头文件(.h.hpp)只包含类的声明和相关的类型定义,而源文件(.cpp)则包含类的实现。

以下是一个简单的示例,展示如何将类的声明和实现分离开来:

头文件(例如:MyClass.h:

// MyClass.h
#ifndef MYCLASS_H // 预处理指令,防止头文件被重复包含
#define MYCLASS_H

class MyClass {
public:
    MyClass(); // 构造函数声明
    ~MyClass(); // 析构函数声明

    // 其他成员函数声明
    void doSomething();

    // 如果有数据成员,也可以在这里声明
    // 但是通常推荐将数据成员设为私有(private)
private:
    int someData; // 示例数据成员
};

#endif // MYCLASS_H

源文件(例如:MyClass.cpp:

// MyClass.cpp
#include "MyClass.h" // 包含头文件以访问类的声明
#include <iostream> // 如果需要使用iostream库,也要包含它

// 构造函数的实现
MyClass::MyClass() {
    someData = 0; // 初始化数据成员
    std::cout << "MyClass constructor called." << std::endl;
}

// 析构函数的实现
MyClass::~MyClass() {
    std::cout << "MyClass destructor called." << std::endl;
}

// 其他成员函数的实现
void MyClass::doSomething() {
    std::cout << "Doing something with MyClass." << std::endl;
    // 可以在这里对数据成员进行操作
    someData++;
}

在上面的示例中,MyClass.h 是头文件,它包含了 MyClass 的声明。而 MyClass.cpp 是源文件,它包含了 MyClass 的实现(即成员函数的定义)。通过包含 MyClass.hMyClass.cpp 可以访问 MyClass 的声明,并为其成员函数提供实现。这种分离使得代码更加模块化,并且可以在多个源文件中重用头文件中的类声明。

string

在C++中,string 是一个非常重要的数据类型,用于存储和操作字符序列(即文本)。string 类型是标准库 <string> 中的一部分,它提供了许多有用的函数来创建、修改和查询字符串。

以下是一些使用 string 类型的基本示例:

包含头文件

首先,你需要包含 <string> 头文件来使用 string 类型。

#include <string>

声明和初始化字符串

std::string str1; // 声明一个空字符串
std::string str2 = "Hello, World!"; // 声明并初始化一个字符串
std::string str3(str2); // 使用另一个字符串初始化
std::string str4(5, 'a'); // 声明并初始化一个包含5个'a'的字符串

访问字符串中的字符

你可以使用下标操作符 []at() 函数来访问字符串中的字符。

char ch = str2[0]; // 获取第一个字符
char ch2 = str2.at(0); // 同样获取第一个字符,但会进行范围检查

修改字符串

你可以通过下标操作符或 assign() 函数来修改字符串中的字符。

str2[0] = 'h'; // 修改第一个字符为小写'h'
str2.assign("new string"); // 分配新的字符串内容

字符串连接

你可以使用 + 操作符或 append() 函数来连接字符串。

std::string str5 = str2 + " and universe!"; // 连接两个字符串
str2.append(" and universe!"); // 同样连接字符串

字符串长度

你可以使用 size()length() 函数来获取字符串的长度。

std::size_t len = str2.size(); // 获取字符串长度

字符串比较

你可以使用 ==<> 等操作符来比较字符串。

if (str2 == "Hello, World!") {
    // ...
}

查找子字符串

你可以使用 find() 函数来查找子字符串在字符串中的位置。

std::size_t pos = str2.find("World"); // 查找"World"在str2中的位置

字符串截取

你可以使用 substr() 函数来截取字符串的一部分。

std::string sub = str2.substr(7, 5); // 从索引7开始截取5个字符

字符串转换

你可以使用其他标准库函数(如 std::stoistd::to_string 等)来在字符串和其他数据类型之间进行转换。

常用函数

构造函数

  • string(): 默认构造函数,创建一个空字符串。
  • string(const string& str): 拷贝构造函数,用另一个字符串初始化。
  • string(const char* s): 用C风格的字符串初始化。
  • string(size_type n, char c): 创建一个包含nc字符的字符串。
  • string(const char* s, size_type n): 用C风格的字符串的前n个字符初始化。
  • string(Initializer_list<char> il): 用初始化列表初始化。

访问函数

  • at(size_type pos) const: 返回位置pos的字符(进行边界检查)。
  • operator[](size_type pos) const: 返回位置pos的字符(不进行边界检查)。
  • front() const: 返回第一个字符。
  • back() const: 返回最后一个字符。
  • data() const: 返回指向字符串内部数组的指针(C风格字符串)。
  • c_str() const: 返回一个以空字符终止的字符数组(C风格字符串)。

容量函数

  • size() const: 返回字符串中的字符数。
  • length() const: 与size()相同,返回字符串中的字符数。
  • max_size() const: 返回字符串可能包含的最大字符数。
  • capacity() const: 返回在不重新分配内存的情况下可以容纳的字符数。
  • empty() const: 如果字符串为空,则返回true
  • reserve(size_type res_arg = 0): 请求改变容量。
  • shrink_to_fit(): 请求移除未使用的容量。

修改函数

  • assign(const string& str): 用另一个字符串替换内容。
  • assign(const string& str, size_type pos, size_type n): 用另一个字符串的子串替换内容。
  • assign(const char* s): 用C风格的字符串替换内容。
  • assign(const char* s, size_type n): 用C风格的字符串的前n个字符替换内容。
  • assign(size_type n, char c): 用nc字符替换内容。
  • append(const string& str): 在字符串末尾添加另一个字符串。
  • append(const char* s): 在字符串末尾添加C风格的字符串。
  • append(const char* s, size_type n): 在字符串末尾添加C风格的字符串的前n个字符。
  • append(size_type n, char c): 在字符串末尾添加nc字符。
  • push_back(char c): 在字符串末尾添加一个字符。
  • pop_back(): 移除字符串末尾的字符。
  • clear(): 移除所有字符。
  • replace(size_type pos, size_type n, const string& str): 替换从位置pos开始的n个字符为另一个字符串。
  • replace(size_type pos, size_type n, const char* s): 替换从位置pos开始的n个字符为C风格的字符串。
  • replace(size_type pos, size_type n, size_type count, char c): 替换从位置pos开始的n个字符为countc字符。
  • erase(size_type pos = 0, size_type n = npos): 移除从位置pos开始的n个字符。
  • insert(size_type pos, const string& str): 在位置pos插入另一个字符串。
  • insert(size_type pos, const char* s): 在位置pos插入C风格的字符串。
  • insert(size_type pos, size_type count, char c): 在位置pos插入countc字符。
  • resize(size_type n, char c = charT()): 改变字符串的大小,如果新大小大于当前大小,则用c填充额外的空间。

搜索和查找函数

  • find(const string& str, size_type pos = 0) const: 从位置pos开始查找子串str
  • find(const char* s, size_type pos = 0) const: 从位置pos开始查找C风格的子串s

这只是 string 类型功能的一小部分。为了充分利用 string 类型,建议查阅C++标准库文档或相关教程以获取更多信息。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

全球最大智能立体书库|北京:3万货位,715万册,自动出库、分拣、搬运

导语 大家好&#xff0c;我是社长&#xff0c;老K。专注分享智能制造和智能仓储物流等内容。 新书《智能物流系统构成与技术实践》 北京城市图书馆的立体书库采用了先进的WMS&#xff08;仓库管理系统&#xff09;和WCS&#xff08;仓库控制系统&#xff09;&#xff0c;与图书…

代码随想录-二叉搜索树(1)

目录 二叉搜索树的定义 700. 二叉搜索树中的搜索 题目描述&#xff1a; 输入输出示例&#xff1a; 思路和想法&#xff1a; 98. 验证二叉搜索树 题目描述&#xff1a; 输入输出示例&#xff1a; 思路和想法&#xff1a; 530. 二叉搜索树的最小绝对差 题目描述&#x…

error: Sandbox: rsync.samba in Xcode project

在Targets 的 Build Settings 搜索&#xff1a;User script sandboxing 设置为NO

基于机器学习的制冷系统过充电和欠充电故障诊断(采用红外热图像数据,MATLAB)

到目前为止&#xff0c;制冷系统故障诊断方法已经产生很多种&#xff0c;概括起来主要有三大类&#xff1a;基于分析的方法&#xff0c;基于知识的方法和基于数据驱动的方法。基于分析的方法主要获得制冷系统的数学模型&#xff0c;通过残差来检测和诊断故障。如果存在残差且很…

SonicSense:声学振动丰富机器人的物体感知能力

在通过声学振动进行物体感知方面&#xff0c;尽管以往的研究已经取得了一些有希望的结果&#xff0c;但目前的解决方案仍然受限于几个方面。首先&#xff0c;大多数现有研究集中在只有少数&#xff08;N < 5&#xff09;基本物体的受限设置上。这些物体通常具有均质材料组成…

电路笔记(电源模块): 基于FT2232HL实现的jtag下载器硬件+jtag的通信引脚说明

JTAG接口说明 JTAG 接口根据需求可以选择20针或14针的配置&#xff0c;具体选择取决于应用场景和需要连接的功能。比如之前的可编程逻辑器件XC9572XL使用JTAG引脚&#xff08;TCK、TDI、TDO、TMS、VREF、GND&#xff09;用于与器件进行调试和编程通信。更详细的内容可以阅读11…

KAIROS复现记录

KAIROS:使用全系统起源的实用入侵检测和调查 Github&#xff1a;https://github.com/ProvenanceAnalytics/kairos KAIROS: Practical Intrusion Detection and Investigation using Whole-system Provenance 1. 论文实验 实验部分使用SCISKIT-LEARN来实现分层特征散列&#xf…

硬核!大佬通过Intel CPU的JTAG接口,DUMP微软原始Xbox的加密BootROM。

这是一篇记录如何通过Intel CPU的JTAG接口,DUMP微软原始Xbox的加密BootROM的文章,内容也记录了老哥如何设计实现JTAG调试器的过程,非常硬核! 原文:JTAG ‘Hacking’ the Original Xbox in 2023 Using Intel CPU JTAG to dump the secret bootrom in Microsoft’s original…

Java代码基础算法练习-求成绩单中最高和第二高的成绩-2024.06.30

任务描述&#xff1a; 输入n(0<n<20)个整数代表成绩&#xff0c;求n个成绩中最高的和第二高成绩 解决思路&#xff1a; 输入的数字 n 为 for 循环的次数&#xff0c;在每次循环中进行值的输入和判断 如果当前输入的分数大于最大值&#xff0c;则更新最大值和次大值 如…

Golang-channel理解

channel golang-channel语雀笔记整理 channelgolang channel的设计动机&#xff1f;chanel的数据结构/设计思考 golang channel的设计动机&#xff1f; channel是一种不同协程之间实现异步通信的数据结构。golang中有一种很经典的说法是要基于通信实现共享内存&#xff0c;而不…

grpc教程——proto文件转go

【1】编写一个proto文件 syntax "proto3"; package myproto;service NC{rpc SayStatus (NCRequest) returns (NCResponse){} }message NCRequest{ string name 1; } message NCResponse{string status 1; } 【2】转换&#xff1a;protoc --go_out. myservice.pro…

重生奇迹MU 正确获取金币的方式

在游戏中&#xff0c;需要消耗大量的金币来购买红药等物品。因此&#xff0c;如何快速赚取金币也成为玩家关注的问题。您知道有哪些方法可以快速地获得金币吗&#xff1f; 一、哪个地图上是最适合打金币的很关键 在选择打钱的地方时&#xff0c;不能盲目行动&#xff0c;需要…

安装maven与nexus

安装maven与nexus Maven官网下载地址&#xff1a;http://maven.apache.org cd /data/software/wget https://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/3.8.1/binaries/apache-maven-3.8.8-bin.tar.gz# 解压 tar xf apache-maven-3.8.1-bin.tar.gz -C /opt/[rooth…

木各力“GERRI”被“GREE”格力无效宣告成功

近日“GERRI”被“GREE”格力无效宣告成功&#xff0c;“GERRI”和“GREE”近似不&#xff0c;如果很近似当初就不会通过初审和下商标注册证&#xff0c;但是如果涉及知名商标和驰名商标&#xff0c;人家就可以异议和无效。 “GERRI”在被无效宣告时&#xff0c;引用了6个相关的…

【启明智显分享】乐鑫ESP32-S3R8方案2.8寸串口屏:高性能低功耗,WIFI/蓝牙无线通信

近年来HMI已经成为大量应用聚焦的主题&#xff0c;在消费类产品通过创新的HMI设计带来增强的连接性和更加身临其境的用户体验之际&#xff0c;工业产品却仍旧在采用物理接口。这些物理接口通常依赖小型显示器或是简单的LED&#xff0c;通过简单的机电开关或按钮来实现HMI交互。…

竞赛 深度学习 大数据 股票预测系统 - python lstm

文章目录 0 前言1 课题意义1.1 股票预测主流方法 2 什么是LSTM2.1 循环神经网络2.1 LSTM诞生 2 如何用LSTM做股票预测2.1 算法构建流程2.2 部分代码 3 实现效果3.1 数据3.2 预测结果项目运行展示开发环境数据获取 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天…

2.2 Python数据类型详解

第二节&#xff1a;Python数据类型详解 Python作为一种动态类型语言&#xff0c;支持多种数据类型&#xff0c;每种数据类型都有其特定的特点和用途。本章将详细介绍Python中常见的数据类型及其特性&#xff0c;以及如何使用这些数据类型进行编程。 2.2.1 整数 (int) 整数是…

黑马点评-Redis的缓存击穿,缓存雪崩,缓存穿透,互斥锁

文章目录 1.缓存穿透2.缓存雪崩3.缓存击穿3.1 互斥锁 1.缓存穿透 解决办法 写入NULL值到Redis缓存&#xff0c;以后就会命中Redis的控制缓存而不会出现请求直接打到数据库的问题&#xff01; 代码 2.缓存雪崩 这个概念很好理解&#xff0c;雪崩就是无数的小雪花结构突然因…

pandas数据分析(1)

pandas&#xff0c;即Python数据分析库&#xff08;Python data analysis library&#xff09; DataFrame和Series DataFrame&#xff08;数据帧&#xff09;和Series&#xff08;序列&#xff09;是pandas的核心数据结构。DataFrame的主要组件包含索引、列、数据。DataFrame和…

扫描全能王的AI驱动创新与智能高清滤镜技术解析

目录 引言1、扫描全能王2、智能高清滤镜黑科技2.1、图像视觉矫正2.2、去干扰技术 3、实际应用案例3.1、打印文稿褶皱检测3.2、试卷擦除手写3.3、老旧文件处理3.4、收银小票3.5、从不同角度扫描文档 4、用户体验结论与未来展望 引言 在数字化时代背景下&#xff0c;文档扫描功能…