【PL理论】(29) OOP:面向对象编程 | 案例研究:C++ 中的类 | 继承 | 继承和指针 | Object-oriented Programming

  • 💭 写在前面:本章我们将进入 Object-oriented Programming,面向对象编程的讲解,探讨 C++ 中的类,继承等。

目录

0x00 面向对象编程

0x01 C语言中的结构体

0x02 案例研究:C++ 中的类

0x03 术语

0x04 继承:动机

0x05 继承和指针


0x00 面向对象编程

另一种重要的编程语言范式,编程是对象的创建和交互。

对象是相关数据和代码的集合,数据 = 属性 (字段) ,代码 = 方法 (函数)。

通常,对象对应于现实世界中的某物。

例如网站系统中的学生对象,网页浏览器引擎中的 HTML 元素对象。

许多现代编程语言在某种程度上支持面向对象编程的概念,例如:C++,Java,Python...

0x01 C语言中的结构体

让我们回顾一下C语言 (它不被认为采用面向对象编程)

struct 用于将一组数据定义为一种新类型,处理这种结构体的函数是单独定义的。

struct Student {
    int id;
    char name[32];
    ...
};

void printStudent(struct Student *x) {
    printf("ID: %d\n", x->id);
    ...
}

0x02 案例研究:C++ 中的类

在 C++ 中,我们定义和使用类,将相关数据 (属性) 和代码 (方法) 绑定在一起。

这种类后来被用来创建对象 (实例),我们还使用访问修饰符 (public 和 private) 来隐藏内部细节,使其不被外部访问。

class Student {
    private:
        int id;
        string name;
    public:
        void Print() {
            cout << "ID: " << id << endl;
            cout << "Name: " << name << endl;
        }
        ...
};

0x03 术语

封装 (Encapsulation) :将相关数据和代码绑定在一起

抽象 (Abstraction) / 信息隐藏 (info hiding):仅暴露必要信息,省略实现细节

我们将学生定义为支持 Print() 等功能的对象,我们使内部细节无法从外部访问。

class Student {
    private:
        int id;
        string name;
    public:
        void Print() {
            cout << "ID: " << id << endl;
            cout << "Name: " << name << endl;
        }
        ...
};

0x04 继承:动机

假设我们要开发学生管理系统,让我们定义 Student 和 Professor 类如下 (注意这次我们为学生添加了 GPA 属性),这两个类共享一些属性和方法。

class Student {
private:
	int id;
	string name;
	double GPA; // Grade Point
public:
	int GetID() { return id; }
	string GetName() { return name; }
	double GetGPA() { return GPA; }
	void Print() { ... }
};

class Professor {
private:
	int id;
	string name;
	string office; // Office room No.
public:
	int GetID() { return id; }
	string GetName() { return name; }
	string GetOffice() { return office; }
	void Print() { ... }
};

然后,这两个类的对象必须分别存储和处理,在下面的示例中,我们必须有单独的数组 (students 和 profs) 和函数 (printStudents 和 printProfs) 。

void printStudents(Student* students[]) { ... }
void printProfs(Professor* profs[]) { ... }
int main() {
	Student* students[MAX_N] = { NULL };
	Professor* profs[MAX_N] = { NULL };
	students[0] = new Student(...);
	profs[0] = new Professor(...);
	...
		printStudents(students);
	printProfs(profs);
	return 0;
}

相反,我们可以从这两个类中提取共同特征,并将其定义为 UnivMem 类,然后,Student 和Professor 类将继承这个类。目前,假设只有UnivMem类具有 Print() 方法。

class UnivMem {
private:
	int id;
	string name;
public:
	int GetID() { return id; }
	string GetName() { return name; }
	void Print() { ... }
};

class Student : public UnivMem {
private:
	double GPA;
public:
	double GetGPA() { return GPA; }
};

class Professor : public UnivMem {
private:
	string office;
public:
	string GetOffice() { return office; }
};

现在,UnivMem 指针可以指向 Student 或 Professor 对象,隐式上转型为 UnivMem 指针,直观上,这很合理,因为 Student 是 UnivMem 的一种。

void printMembers(UnivMem* mems[]) {
	for (int i = 0; mems[i] != NULL; i++)
		mems[i]->Print();
}
int main() {
	UnivMem* members[MAX_N] = { NULL };
	members[0] = new Student(...);
	members[1] = new Professor(...);
	printMembers(members);
	return 0;
}

0x05 继承和指针

如果我们使用一个 Student 指针,我们可以访问对象的所有公共属性和方法,请注意下面的图表仅为概念说明(实际上,方法不存储在对象内存中),此图中不包括私有属性。

与此同时,如果我们使用一个 UnivMem 指针,我们只能访问 UnivMem 类中的公共属性和方法, 即使实际上被这个 UnivMem 指针指向的对象是一个 Student 对象,我们也不能调用 GetGPA() 方法。

在这个例子中,只有第一个调用 s->GetGPA() 会成功编译和运行。

即使 m1 实际上指向一个 Student 对象,m1->GetGPA() 也不会编译通过。

int main() {
	UnivMem* m1, * m2;
	Student* s = new Student(...);
	Professor* p = new Professor(...);
	m1 = s;
	m2 = p;
	cout << s->GetGPA() << endl;  // OK
	cout << p->GetGPA() << endl;  // Error
	cout << m1->GetGPA() << endl; // Error
	cout << m2->GetGPA() << endl; // Error

	return 0;
}


📌 [ 笔者 ]   王亦优
📃 [ 更新 ]   2024.6.10
❌ [ 勘误 ]   /* 暂无 */
📜 [ 声明 ]   由于作者水平有限,本文有错误和不准确之处在所难免,
              本人也很想知道这些错误,恳望读者批评指正!

📜 参考资料 

C++reference[EB/OL]. []. http://www.cplusplus.com/reference/.

Microsoft. MSDN(Microsoft Developer Network)[EB/OL]. []. .

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

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

相关文章

12.3 Go 测试覆盖率

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

关于 python request 的 response 返回 b‘\xa3\xff\xff\x11E .....‘ 类型的数据的解决方案

最近写开发一个爬虫&#xff0c; 程序在本地好好的&#xff0c;返回的是正常的 html&#xff0c; 但是到了生产环境&#xff0c;不知道为什么返回的是一堆乱码 长这样&#xff1a; 查了好几天都没有进展&#xff0c; 对其进行各种转码均无效 今天终于找到解决办法了&#xff…

LabVIEW回热系统热经济性分析及故障诊断

开发了一种利用LabVIEW软件的电厂回热系统热经济性分析和故障诊断系统。该系统针对火电厂回热加热器进行优化&#xff0c;通过实时数据监控与分析&#xff0c;有效提高机组的经济性和安全性&#xff0c;同时降低能耗和维护成本。系统的实施大幅提升了火电厂运行的效率和可靠性&…

永久删除的文件如何恢复?记好这4个方法,轻松恢复文件!

“在清理电脑时&#xff0c;我一不小心把一些还需要的文件永久删除了&#xff0c;不知道大家有没有方法可以恢复这些文件呢&#xff1f;” 在数字时代&#xff0c;我们的生活和工作几乎都离不开电脑和各类存储设备。然而&#xff0c;随着数据的不断增长&#xff0c;误删文件、格…

DNS响应时间分析

目录 什么是DNS响应时间&#xff1f; 为什么DNS响应时间很重要&#xff1f; AnaTraf流量分析仪DNS分析 在当今数字化时代&#xff0c;网络的稳定性和性能对企业的运营至关重要。作为IT运维人员&#xff0c;我们的职责是确保网络顺畅运行&#xff0c;而DNS&#xff08;域名系…

想做副业,如何发现用户需求呢?

点击下方“JavaEdge”&#xff0c;选择“设为星标” 第一时间关注技术干货&#xff01; 免责声明~ 任何文章不要过度深思&#xff01; 万事万物都经不起审视&#xff0c;因为世上没有同样的成长环境&#xff0c;也没有同样的认知水平&#xff0c;更「没有适用于所有人的解决方案…

关于电脑文件的规划思考

概述 设置C、D、E、F 四个盘 C盘&#xff1a;系统数据使用&#xff0c;操作系统、其他软件需要用到的系统性资源 D盘&#xff1a;应用软件区 的使用&#xff0c;数据库、navacat、idea、visual studio、浏览器、向日葵、虚拟机…… E盘&#xff1a;工作区&#xff1a;公司资料…

【云】各家云服务器介绍

文章目录 各主流云服务厂商个人开发者购买什么够用优惠信息 各主流云服务厂商 腾讯云&#xff1a; 优点&#xff1a;腾讯云在程序员圈子中享有“良心云”的美誉&#xff0c;主要是因为其价格性价比高&#xff0c;续费价格也不贵。腾讯云提供了多款云服务器配置&#xff0c;如2核…

物流货运单怎么打印,佳易王货物运单打印查询统计管理系统操作教程

物流货运单怎么打印&#xff0c;佳易王货物运单打印查询统计管理系统操作教程 一、前言 以下软件操作教程以&#xff0c;佳易王物流货运单管理软件为例说明 软件文件下载可以点击最下方官网卡片——软件下载——试用版软件下载 软件操作教程 1、物流开单点击导航栏 物流开单…

碉堡了!云原生大佬撰写的K8s学习指南,有点炸裂,建议运维都收藏!

在这个数字化转型的时代&#xff0c;容器化和云原生技术已成为软件开发的重要趋势。【Kubernetes】作为云原生领域的旗舰项目&#xff0c;不仅是一种容器编排工具&#xff0c;更是构建现代、弹性和可扩展应用程序的基础平台。 因此&#xff0c;对于运维人员来说&#xff0c;学…

【第四篇】SpringSecurity的HttpSecurity详解

SpringSecurity的XML文件配置 在配置文件中通过 security:http 等标签来定义了认证需要的相关信息 SpringSecurity的HttpSecurity配置 在SpringBoot项目中,脱离了xml配置文件的方式,在SpringSecurity中提供了HttpSecurity等工具类,这里HttpSecurity就等同于在配置文件中定…

【算法】Graham 凸包扫描算法 ( 凸包概念 | 常用的凸包算法 | 角排序 | 叉积 | Python 代码示例 )

文章目录 一、Graham 凸包扫描算法1、凸包概念2、常用的凸包算法3、Graham 凸包扫描算法 二、Graham 算法前置知识点1、角排序2、叉积3、算法过程分析 三、代码示例1、完整代码示例2、执行结果 使用 Graham 算法绘制的凸包效果 : 博客代码下载 : https://download.csdn.net/d…

【编程语言】Python平台化为何比Java差?

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌…

[Shell编程学习路线]——if条件语句(单,双,多分支结构)详细语法介绍

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f6e0;️Shell编程专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年6月17日7点50分 &#x1f004;️文章质量&#xff1a;95分 文章目录 ————前言———— &#x1f4af;趣站&#x1f4af…

AI大模型在运动项目的深度融合和在穿戴设备的实践及未来运动健康技术发展

文章目录 1. 技术架构2. 模型选择2.1 LSTM&#xff08;长短期记忆网络&#xff09;2.2 CNN&#xff08;卷积神经网络&#xff09;2.3 Transformer 3. 数据处理数据预处理 4. 实时性要求4.1 边缘计算4.2 模型优化 5. 数据隐私与安全6. 深入分析AI大模型在穿戴设备的应用和未来发…

Harbor镜像中心搭建

文章目录 Harbor镜像中心搭建前置条件下载Harbor创建CA证书配置Harbor开始启动地址映射访问配置本地登录配置外部虚拟机访问 Harbor镜像中心搭建 Harbor是一个镜像中心&#xff0c;我们所熟知的DockerHub就是一个镜像中心&#xff0c;我们可以把我们打包的镜像放在镜像中心中供…

Nuxt3 实战 (九):使用 Supabase 实现 Github 认证鉴权

前言 Supabase 使用的是 postgresql 的 Row Level Security (RLS)&#xff0c;可以限制不同用户对同一张表的不同数据行的访问权限。这种安全机制可以确保只有授权用户才能访问其所需要的数据行&#xff0c;保护敏感数据免受未授权的访问和操作。 Auth Providers 打开 Supab…

Latex的参考文献中显示三个问号???——解决办法

1、问题描述 在使用spring模板&#xff0c;并引用book时&#xff0c;末尾的引文地方出现三个???由于使用的bibtex是直接从谷歌学术中导出来的&#xff0c;其中仅包含作者&#xff0c;书名&#xff0c;出版社&#xff0c;年份等&#xff0c;缺少了重要的信息。结果导致在出版…

【ARM】MDK Debug模式下Disassembly窗口介绍

【更多软件使用问题请点击亿道电子官方网站】 1、 文档目标 主要了解Disassembly窗口中包含的内容&#xff0c;和如何利用Disassembly中的内容了解程序的存储和调用情况。 2、 问题场景 对于Disassembly窗口中具体包含的内容不了解&#xff0c;无法合理地应用Disassembly窗口…

为何云原生是未来?企业IT架构的颠覆与重构(上)

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《未来已来&#xff1a;云原生之旅》&#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、引言 1、什么是云原生 2、云原生的背景和起源 背景 起源 关…