C++中的面向对象到底是什么

news2024/11/26 23:49:48

C++中的面向对象到底是什么

对象嘛,就和大家都有的对象一样,两只眼睛、一个嘴巴、两条腿……
对不起跑题了,C++的面向对象中的对象可不是显示中的对象哦,但是有一些相似之处,有对象的同学可以参考着去学习C++面向对象的概念,没有对象的同学……那就先new一个出来(手动滑稽
在这里插入图片描述

面向对象的概念

对象是对某一类事物的抽象表示,同时具有属性和方法。属性就是这个对象拥有的一些特征,方法就是这个对象可以进行的一些行为。

例如我们大学都必会的“学生管理系统”,用C++面向对象的思想就是,我们把学生看作对象,这个对象拥有身高、姓名、学号、班级、成绩等属性,同时还有修改班级、设置成绩等方法

再例如人也是一个对象,拥有性别、姓名、户籍地等属性,拥有吃饭、睡觉、唱歌等方法。

在C++中,万物皆可对象,也就是我们在开发之前进行系统设计的时候,要从面向对象的角度出发,先考虑如何通过对象的角度去解决问题,规划好各个对象之间的逻辑关系(例如老师可以管理学生,领导可以管理老师等等)。

在C++中,对象是使用类来实现,例如下面的Person类

class Person
{
public:
    void eat();
    void sleep();

private:
    int age;
    string name;
    string sex;
    float hight;
}

对象和实例

对象是对某一类事物的抽象表示,也就是总称;实例就是这个对象的一个具体的例子,同时也是对象,比如人是对象,小明就是对象的一个实例,但是小明也是人。
例如,女朋友是对象,拥有身高、体重、性格、饭量等属性,还有帮你洗衣服、给你做饭、想你撒娇等方法,女朋友A是对象的一个实例,女朋友B也是对象的一个实例,她们的属性数据不同。

我们平常看到的“对象的实例化”、“实例化一个对象”其实都是一个意思,就是由抽象的对象去创建一个个具体的“对象”,因为对象实例化产生的实例也是对象。

在C++中,对象的实例化有下面几种方式

默认构造函数实例化(栈上)

这是最常见的方式,使用类的默认构造函数创建对象。默认构造函数没有参数,它会在对象创建时被调用。下面这种方式是在栈上实例化。

class MyClass {
public:
    MyClass() {
        // 构造函数的实现
    }
};

int main() {
    MyClass obj; // 使用默认构造函数实例化对象
    return 0;
}

带参数的构造函数实例化(栈上)

如果类定义了带参数的构造函数,你可以在实例化对象时传递参数给构造函数,下面这种方式在栈上实例化

class MyClass {
public:
    MyClass(int value) {
        // 构造函数的实现
    }
};

int main() {
    MyClass obj(42); // 使用带参数的构造函数实例化对象
    return 0;
}

无参数动态内存分配实例化(堆上)

使用 new 运算符可以在堆上动态地分配内存,并调用构造函数来实例化对象,需要使用delete手动删除实例化的对象。

class MyClass {
public:
    MyClass() {
        // 构造函数的实现
    }
};

int main() {
    MyClass* obj = new MyClass(); // 使用动态内存分配实例化对象
    // 使用对象
    delete obj; // 释放内存
    return 0;
}

有参数动态内存分配实例化(堆上)

使用 new 运算符可以在堆上动态地分配内存,并调用构造函数来实例化对象,需要使用delete手动删除实例化的对象。

class MyClass {
public:
    MyClass(int value) {
        // 构造函数的实现
    }
};

int main() {
    MyClass* obj = new MyClass(10); // 使用动态内存分配实例化对象
    // 使用对象
    delete obj; // 释放内存
    return 0;
}

在栈上实例化和在堆上实例化的区别

内存管理:

  • 堆上实例化:使用 new 运算符在堆上动态分配内存,对象的生存期由程序员手动控制。需要显式使用 delete 运算符来释放内存,否则可能导致内存泄漏。
  • 栈上实例化:对象在函数的栈帧上自动分配内存,对象的生存期与其所在的作用域相对应。当对象离开作用域时,内存会自动被释放,无需手动管理。

对象访问:

  • 堆上实例化:通过指针来访问对象,需要使用箭头运算符(->)来访问对象的成员。
  • 栈上实例化:通过对象名来直接访问对象的成员。

生命周期:

  • 堆上实例化:对象可以在程序的任意位置创建和销毁,生存期由程序员控制。对象可以在多个作用域中共享。
  • 栈上实例化:对象的生存期与其所在的作用域相对应,当对象离开作用域时,自动被销毁。

对象的大小:

  • 堆上实例化:对象的大小可以是动态的,取决于对象的成员和继承关系。对象的大小可能会影响堆的碎片化。
  • 栈上实例化:对象的大小在编译时确定,通常是固定的。

对象初始化:

  • 堆上实例化:在堆上实例化对象时,可以调用带参数的构造函数来初始化对象。
  • 栈上实例化:在栈上实例化对象时,会自动调用构造函数来初始化对象。

面向对象的三大特性

封装

将一些属性和相关方法“集成”在一个对象中,对外隐藏内部具体的实现细节,外界只需要根据内部提供的接口去使用就可以。

上面的类就体现了封装的概念,实例化一个对象之后,只需要调用它的方法即可,不需要关心内部的实现细节。

继承

我们先明确几个术语:

  • 基类(父类)(Base Class):被继承的类。
  • 派生类(子类)(Derived Class):从基类继承得到的类。
  • 进一步派生的类(孙子类)(Further Derived Class):从派生类再次派生出的类,可以视为“孙”类或更远的后代。

继承就是把父类(也称为基类)的属性和方法继承过来,继承也分为三种,分别是公有继承(public)、保护继承(protected)和私有继承(private)

  • 通过公有继承,基类的公有成员和保护成员在派生类中保持其原有的访问权限(公有成员仍为公有,保护成员仍为保护),而基类的私有成员不能直接被派生类访问,但可以通过基类提供的公有或保护方法来访问。
  • 通过保护继承,基类的公有和保护成员在派生类中都成为保护成员。私有成员仍然保持私有,不可直接访问。
  • 通过私有继承,基类的公有和保护成员在派生类中都成为私有成员。基类的私有成员仍然保持私有,不可直接访问。私有继承通常被用于实现细节的隐藏和复用基类的实现而不是其接口。

详细说下保护继承:
在保护继承中,基类的公有和保护成员在派生类中都成为保护成员,意味着这些成员在派生类内部是可访问的,但是不能被派生类的对象直接访问。也就是说,你不能通过派生类的对象直接访问这些从基类继承来的成员,因为它们在派生类中的访问级别是保护的,而不是公有的。

当我们继续从这样的派生类再派生出新的类时,这些保护成员依然保持保护状态,这意味着在这个新的、进一步的派生类中,这些成员仍然是可访问的。因为保护成员的特性就是允许在类的内部以及这个类的派生类中访问,但不允许通过类的对象进行访问。

假设有三个类:Base、Derived(从Base通过保护继承得来)和FurtherDerived(从Derived类继承得来)。
Base类有一个公有成员和一个保护成员。

由于是保护继承,Derived类中这些成员都成为保护成员,Derived类可以访问这些成员,但Derived类的对象不能直接访问这些成员。

FurtherDerived类,作为Derived的派生类,同样可以访问这些从Base继承来的保护成员,因为保护成员在整个继承链中都保持保护状态,使得它们可以在任何派生类中被访问,但不可以被类的对象直接访问。

这种机制允许在类的内部和其派生类之间共享成员,同时阻止外部访问,从而在一定程度上封装和保护了这些成员。

多态

多多态是面向对象编程中的一个核心概念,它指的是不同类的对象对同一消息的响应方式不同,或者说,同一个接口可以被不同的对象以不同的方式实现。在C++中,多态主要通过虚函数来实现,它允许使用指向基类的指针或引用来调用派生类的方法。

多态主要分为两种类型:静态多态和动态多态。

  • 静态多态(编译时多态):通过函数重载和运算符重载实现。它在编译时决定了使用哪个函数,依赖于参数的数量和类型。
  • 动态多态(运行时多态):主要通过虚函数实现。在运行时根据对象的实际类型来调用相应的方法,实现了接口的统一和行为的多样。

动态多态的实现依赖于以下几个关键点:

  • 虚函数(Virtual Function):在基类中用virtual关键字声明的函数。派生类可以重写(Override)这个函数以提供特定的实现。
  • 纯虚函数(Pure Virtual Function):形式为virtual ReturnType FunctionName() = 0;。含有纯虚函数的类称为抽象类(Abstract Class),不能直接实例化。
  • 基类指针或引用:可以指向派生类的对象,并通过这个指针或引用调用虚函数,实现动态绑定(Dynamic Binding),即在运行时决定调用哪个版本的虚函数。

多态内容较多,我在后面的博客会详细说名这部分内容。

访问权限修饰符

解释一下几种称呼:

  • 派生类:继承自父类的子类;
  • 类外部:除了类内部定义和派生类之外的任何地方。在类外部只能访问该类对象的public成员;
  • 类内部:指的是在类的定义内部,你可以访问所有public、private和protected成员。

public

公有成员可以在类的内部、派生类以及类的外部访问。使用public修饰的成员在类的接口中非常常见,因为它们是类与外界交互的部分。

protected

保护成员可以在类的内部和派生类中访问,但不能在类的外部直接访问。保护访问修饰符在基类中定义成员时特别有用,这些成员需要对派生类可见,但对其他外部类或函数不可见。

protected成员不能被类的对象访问,因为类的对象属于类外部

private

私有成员只能在类的内部访问。即使是该类的派生类也无法访问私有成员。私有访问限制是类封装的一个重要方面,它防止了外部对类内部实现细节的直接访问。

访问权限总结

访问修饰符类内部类外部派生类
public可访问可访问可访问
protected可访问不可访问可访问
private可访问不可访问不可访问

为什么要面向对象编程

面向对象编程,真的是为开发者带来了极大的便利。
在这里插入图片描述
封装我们通过将一类事物封装成一个对象,隐藏内部的实现细节,我们只需要为这个对象设计一组接口,开发者可以直接调用此接口去进行其他操作,而不必思考这个接口内部的实现细节。这种信息隐藏的特性有助于降低系统复杂性,提高模块的独立性,从而使得软件易于理解、修改和扩展。

继承允许新创建的类(派生类)继承现有类(基类)的属性和方法。这促进了代码的重用,允许新的类重写或扩展基类的功能。通过继承,可以创建出具有层次结构的类体系,有助于组织和管理复杂的代码。

多态可以使得一个接口可以用不同的方式来实现,增加了代码的灵活性和可扩展性。这也是实现插件架构和依赖注入等设计模式的关键。

此外,封装、继承和多态也支持了代码的低耦合性,这使得修改和维护现有代码更加容易。

另外,类的抽象性允许开发者专注于高层次的操作,而不是底层的实现细节。通过定义具有通用功能的类,可以创建抽象的表示,这减少了代码的复杂性并提高了代码的可理解性。并且面向对象的概念支持软件工程的基本原则,如模块性、封装性和复用性。这些原则是构建大型系统和复杂应用程序的基石,有助于降低软件开发和维护的复杂性。

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

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

相关文章

niushop单商户V5多店版源码分享三端uniapp打包方法包括PC端_小程序或h5端打包_收银端打包_APP端打包_商户端

目前多店版有四端uniapp,包括PC端uniapp,商家端uniapp,收银端uniapp,门店手机端uniapp,下面我总结下这些端的打包流程希望能帮助到大家,需要交流的可以看我昵称或者点我头像关注我分享代码和教程 一.niush…

原创歌曲分享平台的设计与实现|Springboot+ Mysql+Java+ B/S结构(可运行源码+数据库+设计文档)

本项目包含可运行源码数据库LW,文末可获取本项目的所有资料。 推荐阅读300套最新项目持续更新中..... 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 2024年56套包含ja…

帝国CMS十合一源码/字典/成语/古诗词/二十四节气/英语单词/百家姓/范文文库/词语等

帝国CMS十合一源码/字典/成语/古诗词/二十四节气/英语单词/百家姓/范文文库/词语等 功能包含: 成语大全 二十四节气 英语单词 古诗词 近反义词 词语造句 汉语字典 英文缩写 百家姓 范文文库 文件目录:1个数据库 1个系统源码 1个伪静态规则 安装方式:把1.2G的…

数据结构:非比较排序

非比较排序都具有很大的局限性,包括技术排序,基数排序,桶排序等 计数排序 时间复杂度:O(N) 空间复杂度:O(range) 适用范围 数据的范围集中的数组进行排序,不适合数据分散的数组 方法 统计每个数据出现的次数为n 建立一个相同大小的数组,将每个数据都初始化为0 然后遍历…

在Windows的Docker上部署Mysql服务

在我们做一些和数据库相关的测试时,往往需要快速部署一个数据库作为数据源。如果开发环境是Windows,且开发的代码不依赖于系统,即不用在linux上做开发,则可以将全套环境都部署在Windows上。 本地安装数据库会污染操作系统环境&…

面试题 之 vue

1.vue里怎样实现双向数据绑定? Viewmodel 中的Domlisteners 工具会帮我们检测页面上Dom元素的变化,如果有变化,则更改Model中的数据,更新model中的数据时,数据事件绑定工具会帮我们更新页面中的Dom元素 2.Vue的响应式原…

Autosar-诊断配置详解(免费)-1

1DcM功能简介 诊断通信管理(Diagnostic Communication Manager, DCM)模块作为AutoSar诊断模块的重要组成部分,主要负责诊断数据流和管理诊断状态,包括诊断会话、安全状态及诊断服务分配等。 主要功能贯穿汽车的开发生产及售后等过程,如开发过…

零基础入门转录组数据分析——DESeq2差异分析

零基础入门转录组数据分析——DESeq2差异分析 目录 零基础入门转录组数据分析——DESeq2差异分析1. 转录组分析基础知识2. DESeq2差异分析(Rstudio)3. 结语 1. 转录组分析基础知识 1.1 什么是转录组? 转录组(transcriptome&#…

MATLAB近红外光谱分析技术应用

郁磊副教授,主要从事MATLAB编程、机器学习与数据挖掘、数据可视化和软件开发、生理系统建模与仿真、生物医学信号处理,具有丰富的实战应用经验,主编《MATLAB智能算法30个案例分析》、《MATLAB神经网络43个案例分析》相关著作。已发表多篇高水…

STC8H8K64U 学习笔记 - PWM

STC8H8K64U 学习笔记 - PWM 环境说明引脚说明 PWM呼吸灯震动马达 乐谱 环境说明 该内容仅针对我自己学习的开发板做的笔记,在实际开发中需要针对目标电路板的原理图进行针对性研究。 芯片:STC8H8K64U烧录软件:stc-isp-v6.92G编码工具&#xf…

springJPA如果利用注解的方式 进行多表关联操作

前言:上一篇我写了个用JPA的Specification这个接口怎么做条件查询并且进行分页的,想学的自己去找一下 地址:springJPA动态分页 今天我们来写个 利用jpa的Query注解实现多表联合查询的demo 注意: 不建议在实际项目中用这玩意. 因为: 1. 用Query写的sql 可读性极差,给后期维护这…

C++读取bin二进制文件

C读取bin二进制文件 在C中,可以使用文件输入/输出流来进行二进制文件的读写操作,方便数据的保存和读写。 //C读取bin二进制文件 int read_bin() {std::ifstream file("data_100.bin", std::ios::in | std::ios::binary);if (file) {// 按照二…

go发布包到github

1. 首先,我们在github上创建一个公有仓库并clone到本地 git clone https://github.com/kmust-why/gdmp-token.git cd gdmp-token/ 2. 在gdmp-token工程中初始化go.mod,其中后面的链接要跟github上创建的仓库和你的用户名对应 go mod init github.com/…

手撕算法-有效的括号

描述 分析 使用栈,如果是左括号,入栈,如果是右括号,判断栈是否为空,不是空出栈并校验是否匹配,不匹配返回false。最后如果栈为空,返回true。 代码 class Solution {public boolean isValid(…

【Vue3源码学习】— CH2.6 effect.ts:详解

effect.ts:详解 1. 理解activeEffect1.1 定义1.2 通过一个例子来说明这个过程a. 副作用函数的初始化b. 执行副作用函数前c. 访问state.countd. get拦截器中的track调用e. 修改state.count时的set拦截器f. trigger函数中的依赖重新执行 1.3 实战应用1.4 activeEffect…

Pyhon 大模型常见的微调方式,LLMs常见的Finetune方式;chatglm3微调实战;大模型微调通俗易懂总结

一、 LLMs微调 微调(Fine-tuning)是指在一个已经训练好的神经网络模型基础上,使用额外的数据集或调整超参数,以实现特定任务的训练过程。在微调中,通常会固定预训练模型的大部分参数,只调整最后几层或特定层…

依赖倒转原则

1.1 MM请求电脑 MM电脑坏了,需要修电脑,是因为每次打开QQ,一玩游戏,机器就死了。出来蓝底白字的一堆莫名奇妙的英文。蓝屏死机了,估计内存有问题。 1.2 电话遥控修电脑 遥控修理电脑,打开内存条,两根内存…

前端JS商品规格组合

给定一个数组 let data [{name: "颜色",specs: ["白色", "黑色"],},{name: "尺寸",specs: ["14寸","15寸", "16寸"],},{name: "处理器",specs: ["i5", "i7", "i9&…

【Java代码审计】XXE漏洞

【Java代码审计】XXE漏洞 1.XXE漏洞概述2.Java中的XML常见接口3.XXE 漏洞审计4.XXE漏洞演示XMLReaderSAXReaderSAXBuilderDocumentBuilder 5.XXE漏洞修复 1.XXE漏洞概述 XXE 为 XML 外部实体注入。当应用程序在解析 XML 输入时,在没有禁止外部实体的加载而导致加载…

AdaBoost算法详解自用笔记(1)二分类问题举例分析

AdaBoost算法详解自用笔记(1)二分类问题举例分析 提升方法的思路 AdaBoost作为一种提升方法,其需要回答两个问题:一是每一轮如何改变训练数据的权重或概率分布;二是如何将弱分类器组合成一个强分类器。对于第一个问题…