《C++ primer plus》精炼(OOP部分)——对象和类(1)

news2024/11/28 6:43:28

聪明在于学习,天才在于积累。所谓天才,实际上是依靠学习。

文章目录

  • 概述
  • 正文
    • 面向对象编程和面向过程编程
    • 类和对象
      • 类的组成
      • 公共接口
    • 类声明
      • 访问控制
      • 封装
    • 类和结构体
    • 类定义

概述

C++是门包罗万象的语言,它将各门类的编程思想杂糅,最终造就了它繁琐但几乎无所不能的特点。C++的编程思想主要有四类:面向过程编程(脱胎于c语言),面向对象编程(OOP),STL和泛型编程。就像蛋糕要一块一块啃,学C++也要一部分一部分学。本专栏用《C++ primer plus》中OOP的部分带读者一探OOP思想的魅力。

正文

面向对象编程和面向过程编程

举个例子,如果你要记录一个班学生的成绩。如果用面向过程编程的思想,需要创建一个字符串数组来表示学生的名字,一个int数组来表示学生的分数;如果用面向对象编程,你只需要创建一个表示学生的,这个类表示一个模板,就像一个模具,你可以用这个模具来定制属于自己的对象。就像这样:

class student
{
private:
	string name;
	int grade;
public:
	student(string nm, int g) :name(nm), grade(g) {};
};

int main(void)
{
	student s1((string)"abc", 100);
}

面向对象编程能清楚的表现“A有B”或“A能做B“”的关系。比如一只狗能跑,跳,叫…的能力;一个学生有自己的名字和分数。;面向过程编程则是先做一步,再做下一步,一步一步完成问题。这也就是为什么这两类思想有注重“对象”和“过程”之分。

类和对象

类是一种将抽象转换为用户定义类型的C++工具。说白了,编写程序的人可以将自己脑子里想象出的一类事物用代码的形式写出来,定义为一个新的类型并像使用int,long一样使用它(int也是将抽象的整数类型写成一个类型)。比如,一个名叫Dog的类可能代表狗这一类型。
对象是类的具体化。比如我家养了一只叫做金毛的狗,金毛就可以是狗这一类的对象。

类的组成

类由成员组成,成员分为属性和方法。

  • 属性是这个类所拥有的事物,比如狗可以有四条腿,两只耳朵。属性是这个类的数据部分。
  • 方法是这个类可以进行的动作,比如狗可以奔跑,可以吠叫。方法是这个类的函数部分。
    在编写类时,类规范由两个部分组成:
  • 类声明:包含类的属性部分和方法部分中函数的声明。
  • 类方法定义:包含方法部分函数的实现。

公共接口

对OOP思想有过接触的读者会知道,秉承OOP思想编写的main函数中基本只会调用各个对象的方法来使用这些对象。对于某个对象而言,它可能需要与其他对象互动。总之,一个类必定会定义至少一个需要被外界使用的方法。这些需要被外界使用的方法就被称作公共接口。公共是public的意思,这个关键词接下来会讲到。

接口是一个事物与其他事物进行交互的部分。例如,我们在充电时需要用到插孔,如果没有插孔,就算我们离电线只有一墙之隔,也不可能从电线里拿出电来,此时插孔就可以认为是一个接口。

类声明

下面是一个类声明的例子(类定义和普通的函数定义差不多):

//stock00.h --Stock class interface
#ifndef STOCK00_H_//类声明放到头文件中
#define STOCK00_H_

#include<String>
using namespace std;

class Stock  //class declaration
{
private://这个关键字代表其下是private成员
	string company;
	long shares;
	double share_val;
	double total_val;
	void set_tot() {
		total_val = shares * share_val;
	}
public://这个关键字代表其下是public成员
	void acquire(const string& co, long n, double pr);
	void buy(long num, double price);
	void sell(long num, double price);
	void update(double price);
	void show();
	Stock(const string& co, long n, double pr);
	Stock();
	~Stock();
};	//注意末尾的分号
#endif

剖析这个例子:

  • 将类声明放到头文件中。就像在C语言代码规范中将函数声明放到头文件,类声明也宜放在头文件中。
  • class关键字代表这是一个类。
  • private,public关键字涉及访问控制,暂时不用管。
  • 注意类声明末尾要加分号。
  • public关键词下的方法是公共接口,但set_tot()不是。
  • 最后三个方法分别是两个构造函数和一个析构函数,这两类是极其特殊的没有返回值的函数,在后面会介绍。

访问控制

上述程序中的public(公共),private(私有)关键字体现了OOP中访问控制的思想。被标识为private的属性和方法不能被外部程序直接使用(例如main不能直接使用Stock的set_tot()方法),对于这一点,建议读者自己复制上面的代码放到IDE里试一下。外部程序只能通过public关键字下的方法来使用private成员,因此公共接口就是外部程序与private成员之间的桥梁。这一点意义重大,因为公共接口可以挡掉那些不合法或有害的输入,保证合理的使用private成员。类成员的默认访问控制是private。
事实上,还有第三个关键字protected(保护),这一关键字涉及类继承,将在之后提到。

封装

将实现细节与抽象分开被称为封装。在写出一个类声明时,我们并未想到全部的实现细节,我们想的是这个类能做什么;当外部程序使用这个类时,他们也只是知道这个类能做这件事,而不知道全部的实现细节,这也是一个判断封装的一个小技巧。上面提到,在OOP风格的程序中,main只调用对象的公共接口也是因为实现细节被封装而不能直接调用。封装提供了数据的安全性与隐蔽性,也让以后修改程序时无须修改接口。

类和结构体

在C++中对结构体功能进行了拓展,使其和类几乎完全相同,唯一不同的是struct的默认访问控制是public。但在实际使用中为了方便,我们一般只将struct实现为纯粹的数据对象而不带有方法。

类定义

类定义实质上和函数定义几乎相同,除了两点:

  • 使用作用域解析运算符(::)表示函数使用的类。例如在定义Stock类的acquire方法时,要这么写:
void Stock::acquire(const string& co, long n, double pr)
{
	//方法定义
}
  • 类方法可以访问类的private组件(这是毋庸置疑的!)。

下面是Stock类的一个类定义,建议读者照着敲一遍代码(至少笔者都敲了一遍):

//stock00.cpp --implementing the Stock class
//version 00
#include<iostream>
#include "stock00.h"

void Stock::acquire(const string& co, long n, double pr)
{
	company = co;
	if (n < 0)//对不合理数据的输入的条件测试保证了程序的健壮性
	{
		cout << "Number of shares can't be negative;"
			<< company << " shares set to 0.\n";
		shares = 0;
	}
	else 
		shares = n;
	share_val = pr;
	set_tot();
}

void Stock::buy(long num, double price)
{
	if (num < 0)
	{
		cout << "Number of shares purchased can't be negative."
			<< "Transaction is aborted.\n";
	}
	else
	{
		shares += num;
		share_val = price;
		set_tot();
	}
}

void Stock::sell(long num, double price)
{
	if (num < 0)
	{
		cout << "Number of shares sold can't be negative."
			<< "Transaction is aborted.\n";
	}
	else if (num > shares)
	{
		cout << "You can't sell more than you have!"
			<< "Transaction is aborted.\n";
	}
	else
	{
		shares -= num;
		share_val = price;
		set_tot();
	}
}

void Stock::update(double price)
{
	share_val = price;
	set_tot();
}

/*void Stock::show()
{
	cout << "Company:" << company
		<< "Shares:" << shares << '\n'
		<< "Shares Price:$" << share_val
		<< "Total Worth:$" << total_val << '\n';
}*/

void Stock::show()
{
	using std::cout;
	using std::ios_base;
	//set format to #.###
	ios_base::fmtflags orig = cout.setf(ios_base::fixed, ios_base::floatfield);
	std::streamsize prec = cout.precision(3);

	cout << "Company:" << company
		<< "Shares:" << shares << '\n';
	cout << "Share Price:$" << share_val;
	//set format to #.##
	cout.precision(2);
	cout << "Total Worth:$" << total_val << '\n';

	//restore original format
	cout.setf(orig, ios_base::floatfield);
	cout.precision(prec);
}

Stock::Stock(const string& co, long n,double pr)
{
	company = co;
	if (n < 0)
	{
		std::cerr << "Number of shares can't be nagetive;"
			<< company << "shares set to 0.\n";
		shares = 0;
	}
	else
		shares = n;
	share_val = pr;
	set_tot();
}

Stock::Stock()
{
	company = "no name";
	shares = 0;
	share_val = 0.0;
	total_val = 0.0;
}

Stock::~Stock()
{
	cout << "Bye:" << company << '!\n';
}

请添加图片描述
我是霜_哀,在算法之路上努力前行的一位萌新,感谢你的阅读!如果觉得好的话,可以关注一下,我会在将来带来更多更全面的知识讲解!

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

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

相关文章

Parallels Desktop 19新功能解析,助力跨平台工作流程提升!

对于许多Mac用户来说&#xff0c;运行Windows应用程序是必不可少的。也许你的雇主使用的软件只适用于Windows&#xff0c;或者需要使用依赖于某些Windows技术的网站。或者你想在Mac上玩Windows游戏。或者&#xff0c;你可能需要在其他操作系统上测试应用程序和服务——你可以在…

系统vcomp120.dll丢失怎么办?要怎样修复呢?三个修复方法分享

我要和大家分享一个关于系统丢失vcomp120.dll文件的问题。这个问题可能会困扰很多使用电脑的朋友&#xff0c;特别是在运行某些软件时&#xff0c;可能会出现“找不到vcomp120.dll”的错误提示。那么&#xff0c;遇到这样的问题&#xff0c;我们应该如何解决呢&#xff1f;接下…

用 ChatGPT 写代码太省时间了

几个月前&#xff0c;我们聊过陶哲轩使用 ChatGPT 辅助解决数学问题。当时&#xff0c;他觉得虽然测试结果不太令人满意&#xff0c;但也并没有对 ChatGPT 持完全否定的态度。他觉得&#xff0c;像 ChatGPT 这类大型语言模型在数学中可以用来做一些半成品的语义搜索工作&#x…

【leetcode 力扣刷题】汇总区间//合并区间//插入区间

一些关于区间的力扣题目 228. 汇总区间56. 合并区间57. 插入区间 228. 汇总区间 题目链接&#xff1a;228.汇总区间 题目内容&#xff1a; 看题目真是没懂这个题到底是要干啥……实际上题目要求的恰好覆盖数组中所有数字的最小有序区间范围列表&#xff0c;这个最小是指一个区…

QT 设置应用程序图标

1.下载xx.ico图标&#xff1a;ico网址 2.在线PNG转换ICO&#xff1a;png在线转换ico 3.添加图标资源 1&#xff09;新建文件路径 2&#xff09;添加图片资源 3&#xff09;在 .pro文件里面添加图片 4&#xff09;将xx.ico放到工程目录&#xff0c;编译完可以看到xx.exe的图标…

【LeetCode】515.在每个树行中找最大值

题目 给定一棵二叉树的根节点 root &#xff0c;请找出该二叉树中每一层的最大值。 示例1&#xff1a; 输入: root [1,3,2,5,3,null,9] 输出: [1,3,9]示例2&#xff1a; 输入: root [1,2,3] 输出: [1,3]提示&#xff1a; 二叉树的节点个数的范围是 [0,10^4]-2^31 < No…

无涯教程-JavaScript - CUBERANKEDMEMBER函数

描述 CUBERANKEDMEMBER函数返回集合中的第n个或排序的成员。 使用此功能可返回一组中的一个或多个元素,如销售业绩最好的人或前十名的学生。 语法 CUBERANKEDMEMBER (connection, set_expression, rank, [caption])争论 Argument描述Required/OptionalconnectionThe name …

Linux--进程--创建子进程一般目的

父进程创建子进程的目的&#xff1a;简单来说&#xff1a;给特定的输入&#xff0c;给出特定的输出 父进程希望复制自己&#xff0c;使父、子进程同时执行不同的代码段。这在网络服务进程中是常见的——父进程等待客户端的服务请求。当请求到达&#xff0c;父进程调用fork&…

FPGA 学习笔记:Vivado 工程管理技巧

前言 当前使用 Xilinx 的 FPGA,所以需要熟悉 Xilinx FPGA 的 开发利器 Vivado 的工程管理方法 这里初步列举一些实际 Xilinx FPGA 开发基于 Vivado 的项目使用到的工程的管理技巧 代码管理 做过嵌入式软件或者其他软件开发的工程技术人员,都会想到使用代码管理工具,如 SVN 、…

架构师成长之路Redis第一篇|Redis 安装介绍以及内存分配器jemalloc

安装 Redis官网:https://redis.io/download/ 下载安装二进制文件 可下载安装最新版Redis7.2.0,或者可选版本6.x 我这里下载6.2.13和7.2最新版本,后面我们都是安装6.2.13版本的信息进行讲解 二进制文件安装步骤 安装前期准备: 安装gcc yum install gcc 压缩文件 tar -xzf re…

SpringCloud(34):Nacos服务发现

1 从单体架构到微服务 1.1单体架构 Web应用程序发展的早期,大部分web工程师将所有的功能模块打包到一起并放在一个web容器中运行,所有功能模块使用同一个数据库,同时,它还提供API或者UI访问的web模块等。 尽管也是模块化逻辑,但是最终它还是会打包并部署为单体式应用,这…

Linux:内核解压缩过程简析

文章目录 1. 前言2. 背景3. zImage 的构建过程4. 内核引导过程5. 内核解压缩过程6. 内核加压缩过程小结7. 参考资料 1. 前言 限于作者能力水平&#xff0c;本文可能存在谬误&#xff0c;因此而给读者带来的损失&#xff0c;作者不做任何承诺。 2. 背景 本文基于 ARM32架构 …

【德哥说库系列】-ASM管理Oracle 19C单实例部署

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…

垃圾回收 - 引用计数法

GC原本是一种“释放怎么都无法被引用的对象的机制”。那么人们自然而然就会想到&#xff0c;可以让所有对象事先记录下“有多少程序引用了自己”。让各对象知道自己的“人气指数”&#xff0c;从而让没有人气的对象自己消失&#xff0c;这就是引用计数法。 1、计数器 计数器表…

【Unity基础】1.项目搭建与视图编辑

【Unity基础】1.项目搭建与视图编辑 大家好&#xff0c;我是Lampard~~ 欢迎来到Unity基础系列博客&#xff0c;终于要开始写基础系列的博客了&#xff0c;前两篇的内容基本上与入门系列相同&#xff0c;如果有紧跟入门系列的同学可以直接从第三篇文章开始看 好了话不多说我们开…

Java切换到Kotlin,Crash率上升了?

前言 最近对一个Java写的老项目进行了部分重构&#xff0c;测试过程中波澜不惊&#xff0c;顺利上线后几天通过APM平台查看发现Crash率上升了&#xff0c;查看堆栈定位到NPE类型的Crash&#xff0c;大部分发生在Java调用Kotlin的函数里&#xff0c;本篇将会分析具体的场景以及…

ORB-SLAM3复现过程中遇到的问题及解决办法

在复现过程中遇到的问题的解决过程 1. 版本检查1.1 Opencv版本的检测1.2 Eigen版本的检测1.3 查看Python版本1.4 其他 2. 编译过程中遇到的问题及解决办法2.1 ./build.sh遇到的问题2.2 ./build_ros.sh遇到的问题 因为环境比较干净&#xff0c;所以遇到的问题相对少一些&#xf…

ARM 汇编基础知识

1.为什么学习汇编&#xff1f; 我们在进行嵌入式 Linux 开发的时候是绝对要掌握基本的 ARM 汇编&#xff0c;因为 Cortex-A 芯片一 上电 SP 指针还没初始化&#xff0c; C 环境还没准备好&#xff0c;所以肯定不能运行 C 代码&#xff0c;必须先用汇编语言设置好 C 环境…

【python】实现积分

借助sympy.integrate() 符号运算库&#xff0c;所以里面的exp()&#xff0c;sin()等都要使用sympy库中的函数&#xff0c;如果使用numpy库中的函数时没用的。 import sympy as sp import numpy as np x sp.symbols("x") print(sp.integrate(sp.exp(-x**2), (x, -s…

企业数据加密软件——「天锐绿盾」

「天锐绿盾」是一款企业数据加密软件&#xff0c;主要用于防止企业计算机信息被破坏、丢失和泄密。该软件采用文件过滤驱动实现透明加解密&#xff0c;对用户完全透明&#xff0c;不影响用户操作习惯。 PC访问地址&#xff1a; isite.baidu.com/site/wjz012xr/2eae091d-1b97-4…