初始类与对象

初始类与对象

实验介绍

本课程是进一步对类与对象的深入认识,如何定义并实例化一个类,介绍如何使用 C++ 标准库 string 类等。

知识点
  • 认识类与对象
  • 内联函数
  • string
  • 类的定义与实例化

认识类与对象

官方定义

类:在面向对象编程中是一种面向对象计算机编程语言的构造,是创建对象的蓝图,描述了所创建的对象共同的属性和方法。

对象:通过类创建出对象,又称实例化对象。

深入理解类

类是 C++ 的核心特性,在 C++ 的世界中,可以将所有事物都看作为一个对象,将对象进行封装之后成为一个类,通常被称为用户定义类型。

例如:可以将猫、狗、鸟、桌子、学生、人、三角形、矩形等都封装为一个类,只要在实际编程中用到的都可以抽象封装为一个类。

C++ 相关概念
概念描述
构造函数类的构造函数是一种特殊的函数,在创建一个新的对象时自动调用
析构函数类的析构函数也是一种特殊的函数,在删除所创建的对象时自动调用
拷贝构造函数拷贝构造函数,是一种特殊的构造函数,它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象
友元函数友元函数可以访问类的 privateprotected 成员
内联函数通过内联函数,编译器试图在调用函数的地方扩展函数体中的代码
类成员函数类的成员函数是指那些把定义和原型写在类定义内部的函数,就像类定义中的其他变量一样
类访问修饰符类成员可以被定义为 publicprivateprotected。默认情况下是定义为 private
this 指针每个对象都有一个特殊的指针 this,它指向对象本身
静态成员类的数据成员和成员函数都可以被声明为静态的

自定义类

假设最近在做一个学校管理系统的项目,首先想到可以将学生定义为一个类,然后发现可以在学生类的基础上再抽象出一个人类的对象,如果需要用到学生的学科,可以进一步将学科也封装为一个,还可以封装文件操作类,数据库操作类等等。

示例代码 1

定义一个学生类:

#include <iostream>
#include <string>
using namespace std;// class 类关键字、Student 类名
class Student
{
// 访问限制符 - 公有属性
public:Student() {}    // 构造函数~Student() {}    // 析构函数// 成员函数void setName(string name) { this->name = name; }string getName() const { return name; };void setAge(int age) { this->age = age; }int getAge() const { return age; }
// 访问限制符 - 私有属性
private:// 数据成员string name;int age;
};

类定义注意事项:

  1. 定义一个类时,需要使用关键字 class 来进行修饰。
  2. 一个简单的类可以没有构造函数和析构函数,但是系统自动生成一个默认的构造函数和析构函数。
  3. 在类中使用关键字 publicprivateprotected 来限制数据成员和成员函数,一般使用 publicprivate 来修饰数据成员和成员函数。
  4. 一般将数据成员封装在 private 关键字下,不让用户直接访问数据成员,而是通过成员函数来进行访问。
  5. 在类的最后(大括号后)必须要有一个分号,勿忘。

实例化对象

实例化对象有两种方式,一种是在栈上实例化,另一种是在堆上实例化。

示例代码 2
int main()
{// 栈上实例化Student stu1;stu1.setName("jake");stu1.setAge(15);cout << "My name is " << stu1.getName() << ", I'm " << stu1.getAge() << " years old." << endl;// 堆上实例化Student *stu2 = new Student;// 访问stu2->setName("Siri");stu2->setAge(5);cout << "My name is " << stu2->getName() << ", I'm " << stu2->getAge() << " years old." << endl;// 释放内存delete stu2;stu2 = nullptr;return 0;
}

实例化对象注意事项:

  1. 在栈上实例化的对象,超出定义域对象资源会自动被系统回收。
  2. 在堆上实例化的对象,最后需要使用 delete 关键字来释放内存,否则会造成内存泄漏。
  3. 使用栈实例化的对象使用 “.” 来访问数据成员或成员函数,在堆上实例化的对象使用 “->” 来访问数据成员或成员函数。
  4. 释放完内存后将对象置空,防止野指针。

string 类

C++ 标准库:前人开发时编写的类,并被收录成为通用的标准类,之后的人开发时可以直接使用,避免重复造轮子。string 类是开发时经常会使用到的一个类。

string 类是 C++ 标准库中的字符串类,专用于字符串操作,接下来介绍一下如何使用 string 类。

string 介绍

  1. string 类头文件 #include<string>
  2. string 类在 std 命名空间内。
  3. 使用 string 实例化一个字符串类型的对象。
  4. 对字符串对象执行例如拼接、查找等操作。
string 初始化方式
实例化解释
string s1;s1 为空字符串
string s2(“ABC”);s2 初始值为 “ABC”
string s3 = s2;
string s3(s2);s3 初始化为 s2 的一个副本
string s4(n, ‘c’ );s4 初始化为字符 ‘c’ 的 n 个副本
string 常用操作

以下列出了 string 经常使用的操作,如果还需要用到其他操作可以在 官网 查找 string 类的相关使用方法,里面配有示例程序。

操作解释
s.empty()判断 s 是否为空,如果 s 为空返回 true,否则返回 false
s.size()返回 s 中字符的个数,和 s.length() 功能相同
s[n]返回 s 中位置 n 的字符,位置从 0 开始。切记不要越界
s1 + s2将 s1 和 s2 连接成新字符串,返回新字符串
s1 = s2赋值,将 s2 内容赋值给 s1
s1 == s2判断相等,相等返回 true,否则返回 false
s1 != s2判断不等,不等返回 true,否则返回 false
s.c_str()返回 char*,和 s.data() 功能相同
stoi()字符串转 int,还有 stol(),stoll()
stof()字符串转 float, 还有 stod(),stold()
示例代码 3

string 类提供丰富的初始化方式,但也需要注意示例中错误的初始化方式。

// string 初始化
#include <iostream>
#include <string>
using namespace std;int main()
{string s1;string s2 = "hello";string s3("world");string s4 = s1 + s2;string s5 = "hello " + s2;string s6 = "hello " + s2 + "world";string s7(5, 'c');string s8 = "hello" + " world"; // Errorreturn 0;
}
示例代码 4

string 类在实际开发中经常使用,功能也是相当的强大,下面通过示例代码来体验一下。

#include <iostream>
#include <string>
using namespace std;int main()
{// 初始化string s1 = "hello";string s2 = "this is shiyanlou.";// size() 和 length() 都是返回字符串的长度cout << "s1.size() = " << s1.size() << endl;cout << "s1.length() = " << s1.length() << endl;// 需要注意 capacity() 是返回 string 的当前容量,string 本身是一个数组,所以 capacity() 返回的长度可能会大于 size() 或者 length() 返回的长度cout << "s1.capacity() = " << s1.capacity() << endl;// s1.at(i) 和 s1[i] 都是访问位置 i 的字符cout << "s1.at(1) = " << s1.at(1) << endl;cout << "s1[1] = " << s1[1] << endl;// find() 查到字符,找到返回字符串位置,否则返回 -1cout << "s1.find('e') = " << s1.find('e') << endl;// 指定起始位置查到cout << "s2.find(\"is\", 4) = " << s2.find("is", 4) << endl;// 逆序查找cout << "s2.rfind(\"is\") = " << s2.rfind("is") << endl;// 判断字符串是否为空if (s1.empty()) {cout << "s1 is empty." << endl;}else {cout << "s1 is not empty." << endl;}// 判断字符串是否相等if (s1 == "hello") {cout << "s1 == hello" << endl;}else {cout << "s1 != hello" << endl;}// string --> intstring s3 = "1314";cout << "stoi(s3) = " << stoi(s3) << endl;// string --> floatstring s4 = "3.1415";cout << "stof(s4) = " << stof(s4) << endl;return 0;
}

内联函数

官方定义:内联函数又是称作 “在线函数” 或者 “编译时期展开函数” 的一种编程语言结构,用来建议编译器对一些特殊函数进行内联扩展;也就是说建议编译器将制定的函数体插入并取代每一次调用该函数的地方,从而节省每次调用函数带来的额外时间开支。

  1. 定义内联函数关键字:inline
  2. 内联分为普通内联函数和类内联函数。
  3. 定义内联函数时一般使用于简单的函数,如果函数比较复杂,编译器也将自动取消内联。
普通内联函数 - 示例代码 5
#include <iostream>
using namespace std;int max(int a, int b)
{return a > b ? a : b;
}inline int min(int a, int b)
{return a > b ? b : a;
}int main()
{int a = 5, b = 7;// 普通函数求最大值cout << "max(a, b) = " << max(a, b) << endl;// 内联函数求最小值cout << "min(a, b) = " << min(a, b) << endl;return 0;
}
编译过程

类内联函数

如下图是使用类内定义一个类的方法(“类的定义域实例化” 小节中会讲到类内定义),而使用类内定义的成员函数编译器会默认将成员函数当做为内联函数进行编译。但如果成员函数比较复杂,编译器也不会将成员函数当做内联函数进行编译。

小结
  1. 编译器在编译时会将内联函数直接插入到调用内联函数处,这样可以减去调用函数时的开销。
  2. 在实际开发过程中,可以酌情考虑使用类内定义的方法实现类成员函数。

类的定义与实例化

在学习本小节之前先来学习另外两个知识点。

  • 类内定义。
  • 类外定义。
  • 同文件类外定义。
  • 分文件类外定义。

在实际开发过程中需要考虑到程序的架构问题,类内定义适用于一个相对比较简单的程序,考虑到开发时的方便性和时间成本,类外定义是实际程序开发中常用的方法。

类内定义

类内定义即在类中实现成员函数。

示例代码 6
#include <iostream>
#include <string>
using namespace std;class Student
{
public:Student() {}~Student() {}// 定义成员函数并实现功能void setName(string name) { this->name = name; }string getName() const { return name; };void setAge(int age) { this->age = age; }int getAge() const { return age; }
private:string name;int age;
};int main()
{Student stu;stu.setName("jake");stu.setAge(15);cout << "My name is " << stu.getName() << ", I'm " << stu.getAge() << " years old." << endl;return 0;
}
小结

在以上示例代码中,类中定义的成员函数都是使用的类内定义的方式实现的,在实际的开发中不建议这样做,除非是定义一个非常简单的类或者成员函数。

在内联函数小节中提到过,类内定义的方式编译器会自动尝试将成员函数作为内联函数进行编译,如果成员函数比较复杂,编译器将不会作为内联函数进行编译。

类外定义

类外定义有两种方式:

  1. 同文件类外定义。
  2. 分文件类外定义。
同文件类外定义 - 示例代码 7
#include <iostream>
#include <string>
using namespace std;class Student
{
public:Student();~Student();void setName(string name);string getName() const;void setAge(int age);int getAge() const;
private:string name;int age;
};Student::Student()
{
}Student::~Student()
{
}void Student::setName(string name)
{this->name = name;
}string Student::getName() const
{return name;
};void Student::setAge(int age)
{this->age = age;
}int Student::getAge() const
{return age;
}int main()
{Student stu;stu.setName("jake");stu.setAge(15);cout << "My name is " << stu.getName() << ", I'm " << stu.getAge() << " years old." << endl;return 0;
}
分文件类外定义 - 示例代码 8
// Student.h 文件
#ifndef __STUDENT__
#define __STUDENT__
#include <iostream>
#include <string>
using namespace std;class Student
{
public:Student();~Student();void setName(string name);string getName() const;void setAge(int age);int getAge() const;
private:string name;int age;
};#endif // __STUDENT__
// Student.cpp 文件
#include "Student.h"    // 记得添加类头文件Student::Student()
{
}Student::~Student()
{
}void Student::setName(string name)
{this->name = name;
}string Student::getName() const
{return name;
};void Student::setAge(int age)
{this->age = age;
}int Student::getAge() const
{return age;
}
// main.cpp 文件
#include <iostream>
#include "Student.h"int main()
{Student stu;stu.setName("jake");stu.setAge(15);cout << "My name is " << stu.getName() << ", I'm " << stu.getAge() << " years old." << endl;return 0;
}

文件结构以及运行结果截图:

小结

同文件类外定义就是将类的成员函数定义在类之外的地方,同时类的成员函数使用类作用域来进行定义。在实际项目开发中,类不是很复杂时可以使用该方法,类比较复杂时不推荐使用。

分文件定义类就是将类的定义放在 xxx.h 头文件中,而类的成员函数实现放在 xxx.cpp 文件中。这种做法是做项目时推荐使用的方法,因为这样将类的定义和成员函数分开后,在开发时很容易能够查找到对应的定义和成员函数。

一般情况下文件名和类名相同,便于开发时类管理。

实验总结

知识点总结
  • 深入认识类与对象并讲解 C++ 相关概念。
  • 如何使用 string 类。
  • 普通内联函数与类内联函数以及编译器对内联函数的处理。
  • 学习类内定义与类外定义,开发时常使用分文件类外定义的方法。
  • main 函数的返回值为 int 类型,注意不要写成 void 类型。
章节总结

本章节讲解的是比较基础的知识点,但是在开发中却非常的重要,在接下来的章节中将会越来越深的学习 C++ 知识。

希望在本章节结束后能掌握如何定义和使用类,并且掌握在工作中的实际用法。

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

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

相关文章

自定义starter案例——统计独立IP访问次数

自定义starter案例——统计独立IP访问次数 文章目录 自定义starter案例——统计独立IP访问次数ip计数业务功能开发定时任务报表开发使用属性配置功能设置功能参数配置调整 自定义拦截器开启yml提示功能 ip计数业务功能开发 public class IpCountService {private Map<String…

matplot函数调整子图大小测试

调整subplot()函数的子图间距 import numpy as np import matplotlib.pyplot as plt for i in range(1,7):figsize 10,6plt.subplot(2,3,i)plt.text(0.5,0.5,str((2,3,i)),fontsize18,hacenter) **plt.subplots_adjust(hspace3.3, wspace0.3)** plt.show()import numpy as np…

水果党flstudio用什么midi键盘?哪个版本的FL Studio更适合我

好消息&#xff01;好消息&#xff01;特大好消息&#xff01; 水果党们&#xff01;终于有属于自己的专用MIDI键盘啦&#xff01; 万众期待的Novation FLKEY系列 正式出炉&#xff01; 话有点多话&#xff0c;先分享一份干货&#xff0c;尽快下载 FL Studio 21 Win-安装包&…

2023人工智能和市场营销的融合报告:创造性合作的新时代需要新的原则

今天分享的人工智能系列深度研究报告&#xff1a;《2023人工智能和市场营销的融合报告&#xff1a;创造性合作的新时代需要新的原则》。 &#xff08;报告出品方&#xff1a;M&CSAATCHITHINKS&#xff09; 报告共计&#xff1a;11页 生成型人工智能的兴起和重要性 生成式…

P8 Linux 目录操作

目录 前言 01 mkdir 系统调用 mkdir的代码示例 02 rmdir删除目录 03 打开、读取以及关闭目录 3.1 opendir()函数原型&#xff1a; 04 读取目录 readdir() 05 struct dirent 结构体&#xff1a; 06 rewinddir ()函数重置目录流 07 关闭目录 closedir ()函数 测试:打印…

基于深度学习的遥感图像变化差异可视化系统

1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 研究背景与意义 遥感图像变化差异可视化是遥感图像处理和分析的重要研究领域之一。随着遥感技术的快速发展和遥感数据的广泛应用&#xff0c;遥感图像的获取和处理变得越来越容易…

python-比较Excel两列数据,并分别显示差异

利用 openpyxl 模块&#xff0c;操作Excel&#xff0c;比较Excel两列数据&#xff0c;并分别显示差异 表格数据样例如下图 A&#xff0c;B两列是需要进行比较的数据&#xff08;数据源为某网站公开数据&#xff09;&#xff1b;C&#xff0c;D两列是比较结果的输出列 A&#…

小白学习java理解栈手写栈——第四关(青铜挑战)

内容1.理解栈的基本特征2.理解如何使用数组来构造栈3.理解如何使用链表来构造栈 1.栈的基础知识 1.1栈的特征 栈和队列是比较特殊的线性表&#xff0c;又称为访问受限的线性表。栈是很多表达式、符号等运算的基础&#xff0c;也是递归的底层实现&#xff0c;理论上递归能做的…

Linux 防病毒软件:CentOS有哪些付费的防病毒软件

CentOS是一个基于开源的Linux发行版,通常不像Windows那样普遍需要使用付费的防病毒软件。大多数Linux系统侧重于使用开源和免费的安全工具来保护系统。一些常见的免费和开源的防病毒软件和安全工具包括ClamAV、Sophos Antivirus for Linux、rkhunter、chkrootkit等。 如果你非…

[数据集][目标检测]拉横幅识别横幅检测数据集VOC+yolo格式1962张1类别

数据集格式&#xff1a;Pascal VOC格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;1962 标注数量(xml文件个数)&#xff1a;1962 标注数量(txt文件个数)&#xff1a;1962 标注类别数&a…

探索Scrapy-spider:构建高效网络爬虫

Spider简介 Scrapy中的Spider是用于定义和执行数据抓取逻辑的核心组件。Spider负责从指定的网站抓取数据&#xff0c;并定义了如何跟踪链接、解析内容以及提取数据的规则。它允许您定制化地指定要抓取的网站、页面和所需的信息。Spider的作用是按照预定的规则爬取网页&#xf…

边缘计算与人工智能的融合

随着物联网技术的迅猛发展&#xff0c;大量设备和传感器开始连接至互联网&#xff0c;产生了海量的数据。传统的云计算模式往往无法满足对数据实时性和隐私保护的需求&#xff0c;而边缘计算技术的兴起为解决这一难题提供了新的思路。边缘计算将数据处理和分析的功能下沉至数据…

产品成本收集器流程演示

感谢大佬的文章&#xff0c;我只是一个翻译搬运工&#xff0c;原文地址&#xff1a;产品成本收集器 概述 SAP 令人兴奋的部分之一是它在不同操作模块之间的集成程度。使用产品成本收集器来跟踪生产就是一个很好的例子。在本博客中&#xff0c;我计划遵循产品成本收集器流程&a…

JAVA刷题之数组的总结和思路分享

꒰˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱ ʕ̯•͡˔•̯᷅ʔ大家好&#xff0c;我是xiaoxie.希望你看完之后,有不足之处请多多谅解&#xff0c;让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客 本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN …

C语言第十六集(前)

1.关于那个整形存储入char的 是先取好补码,再截断 例: 2.%u是以十进制的形式打印无符号整数 3.注意(背):存储的char类型变量的补码为10000000的直接解析为-128 4.signed char 类型的变量取值范围是-128~127 5.unsigned char 类型的变量取值范围是0~255 6.有符号类型的变量…

2023.12.6 关于 Spring Boot 事务的基本概念

目录 事务基本概念 前置准备 Spring Boot 事务使用 编程式事务 声明式事务 Transactional 注解参数说明 Transational 对异常的处理 解决方案一 解决方案二 Transactional 的工作原理 面试题 Spring Boot 事务失效的场景有那些&#xff1f; 事务基本概念 事务指一…

如何解决5G基站高能耗问题?

安科瑞 须静燕 截至2023年10月&#xff0c;我国5G基站总数达321.5万个&#xff0c;占全国通信基站总数的28.1%。然而&#xff0c;随着5G基站数量的快速增长&#xff0c;基站的能耗问题也逐渐日益凸显&#xff0c;基站的用电给运营商带来了巨大的电费开支压力&#xff0c;降低5…

vue项目配置多个代理

在本地.env文件配置本地/测试/预发/正式 路径&#xff1a; 在vue.config.js 里面配置&#xff1a; module.exports defineConfig({transpileDependencies: false,lintOnSave: false,outputDir: process.env.VUE_APP_DIST,publicPath: /,css: {loaderOptions: {postcss: {// p…

Motion Plan之轨迹生成代码实现 (1)

Motion Plan之搜索算法笔记Motion Plan之基于采样的路径规划算法笔记Motion Plan之带动力学约束路径搜索 Motion Plan之轨迹生成笔记文章开始前先回顾下上次的带约束的轨迹生成&#xff0c;轨迹生成本质就是曲线拟合。曲线拟合常用的方法有&#xff1a;多项式、贝赛尔曲线、三…