C++面对对象编程

面对对象编程入门

  • 1.类与对象
  • 2.公有和私有概念
  • 3.类的成员函数
  • 4.类的实例化
  • 5.构造函数
  • 6.析构函数
  • 7.常成员函数
  • 8.静态属性和静态方法
  • 总结

1.类与对象

在python中,我们提到过类这个概念。所谓类,就是一个包含着元素和函数的数据类型,在C++中,系统数据类型(如int、char等)都是由类进行定义的,我们当然也可以定义自己需要的数据类型。类是面对对象编程的重要概念,我们可以把它理解成一系列特征的集合。对象则是类的具象化,他可以拥有类中包含的多个特征,而具体要包含哪些特征则需要根据实际需求确定。类中存储的数据叫做类的属性,包含的函数叫做类的方法。

2.公有和私有概念

公有和私有的概念用于规定类定义的属性与方法在哪里可以被使用。通常,公有的内容可以在类内进行使用,也可以在类外进行使用,而私有的内容则只能在类内直接使用。在python中,类里创建的成员默认都是公有的,然而C++却必须要我们声明哪些内容是私有,而哪些内容是公有的。如果我们不加以声明,计算机就会报错。下面我们举一个简单的例子,初步了解类的定义以及公有和私有的概念:

class Student // 定义一个Student类
{public: // 定义共有内容,以定义name属性为例std::string name;private: // 定义私有内容,以定义age属性为例int age;
};

这样定义的Student类型,就有了两个属性,其中name为公有属性。这样的类与C语言中结构体有些相似,但类除了可以集成变量,还能够集成函数。

3.类的成员函数

类中不光有数据,还可以有函数。类中包含的函数叫做类的成员函数,也叫做方法。类方法的声明和定义与面对过程编程中函数的声明和定义很像,我们可以在类中先声明方法,然后再类外进行定义,也可以把声明和定义放在一起。当然,在声明方法之前,我们也需要告诉计算机该方法是私有还是公有:

class Student
{public: std::string name;int grade(int Chinese,int English,int math);private:int age;
};
int Student::grade(int Chinese,int English,int math)
{return Chinese+English+math;
}

以上是在类外定义方法的情况,后面的例子大多是在类内定义方法,这里不做赘述。需要注意的是,在类内定义的方法都是内联函数,而类外定义的方法需要有inline修饰才是内联函数。设置成私有属性时声明和定义的方法与公有一样。

4.类的实例化

类有了定义,我们就需要了解一下如何使用类。通常,使用类需要对类进行实例化,所谓实例化,就是将抽象的类具象化为一个实例:

// 这里使用的Student类为第三节中定义的类
int main()
{Student ZhangSan; // ZhangSan为类的一个实例ZhangSan.name="ZhangSan"; // 给实例ZhangSan的name赋值// ZhangSan.age=20; // 报错,无法赋值cout<<ZhangSan.name<<" "<<ZhangSan.grade(100,99,98)<<endl;
}
// 输出为:ZhangSan 297

从这个例子中可以看出,我们实例化一个Student类型的变量ZhangSan之后,可以用点号运算符调用ZhangSan所在类的公共属性与方法,但是私有属性是不可以被调用的。这与python的类很像。

5.构造函数

构造参数在python中我们也学习过,它是在该类被实例化后就会立刻自动执行的方法。比如我们使用 int a 声明一个参数a,那么a会被自动赋予初值,这个过程就是依赖构造函数实现的。在C++中,构造函数是与类同名的方法,如果需要使用构造函数,首先需要定义一个没有参数的构造函数,如:

class Student
{public: std::string name;int age;Student() // 构造函数没有返回值,也可以在函数外面定义// 这里实现给两个方法赋值的功能{age=0;name="ZhangSan";}
};

我们再来实例化一个ZhangSan,然后看看他的属性是什么:

int main()
{Student ZhangSan;cout<<ZhangSan.name<<" "<<ZhangSan.age<<endl;
}
// 输出为:ZhangSan 0

这就很像实例化一个int类的a,a会自动获得初值。但是,我们在对int类进行实例化时,也可以给这个实例一个值,如int a=10。C++若想实现这个功能,就需要对构造函数进行重载。下面这个例子我会同时演示重载构造函数以及在类外定义构造函数:

class Student
{public: string name;int age;Student(); // 想定义有参数构造函数时,无参数构造函数也不可以省略Student(int a,string b);
};
Student::Student()
{age=0;name="ZhangSan";
}
Student::Student(int a,string b)
{age=a;name=b;
}

但是我们要注意,在实例化Student类后,可不能用等于号为实例赋age和name。调用有参数的构造函数只能这样写:

int main()
{Student LiSi(20,"LiSi");cout<<LiSi.name<<" "<<LiSi.age<<endl;
}

当然,我们还可以用初始化列表为属性赋值,这个我们放在下节介绍。
python的构造函数就是__init__(),由于可变参数、默认参数、self参数的存在,很多C++中需要函数重载才能实现的功能在python中可以非常容易的实现。

6.析构函数

在这里我借题发挥,给大家简单介绍一下动态空间开辟。在python中,如果我们想给如列表这样的类型增加或删除元素,可以直接调用append、pop之类的方法,这是因为列表类是允许改变其实例所占空间大小的。然而,在C++中,一个类型的大小是在声明时就已经决定的。如果想要改变其大小,就需要进行动态空间开辟。动态空间开辟一旦开始,就必须在适当的位置停止,否则会留下隐患。
析构函数的定义方法与构造函数很像,只是它的函数名是“~类名”。析构函数的主要是在合适的时机(如对象超出其作用域或者程序结束时)自动运行,销毁需要销毁的内容(如类内动态开辟的空间)。举一个简单的例子,看不懂的小伙伴删除标记位置的代码再看即可,析构函数不做重点介绍,大家看一下他是在什么时候执行即可:

class Student
{public:int age;// 动态空间开辟:/*不懂可删*/int* ptr1=new int;/*不懂可删*/int* ptr2=new int[10];string name;Student(){age=0;name="ZhangSan";}~Student()  // 析构函数没有参数,需要写清理代码。写其他内容也不影响执行// 当类中不存在需要手动清理的内容,就不需要自定义析构函数{/*不懂可删*/delete ptr1; // 清除动态开辟的单个类型/*不懂可删*/delete [] ptr2; // 清除动态开辟的数组类型cout<<"析构函数已执行!"<<endl;}int grade(int Chinese,int English){return Chinese+English;}
};int main()
{Student ZhangSan;cout<<ZhangSan.age<<ZhangSan.name<<endl;cout<<ZhangSan.grade(98,100)<<endl;cout<<"我们不再需要张三了"<<endl;
}
// 输出为:0ZhangSan
//        198
//        我们不再需要张三了
//        析构函数已执行!

有兴趣的效果版可以debug一下,在这个例子中析构函数是在主函数内容都已经运行完成后才返回到实例化Student类的那一步执行的。

7.常成员函数

常成员函数也是类方法的一种,只需在声明和定义函数后再加一个const标识即可。常成员函数可以读取类属性,但是不能对其进行修改;常成员函数能且仅能调用常成员函数,这是为了防止常成员函数调用普通成员函数间接修改类内成员。举例如下:

class Student
{ public:int age;string name;Student(){age=0;name="ZhangSan";}void amand(int a) // {age=a;}bool read () const // 定义常成员函数,代表该函数为常成员函数,只读不写{// amand(10); // 由于amand函数非常成员函数,因此不能被调用cout<<name;cout<< age;return true;}
};int main()
{Student ZhangSan;ZhangSan.read();
}

8.静态属性和静态方法

静态函数和静态数据用于描述全局,作用域与主函数相同,静态内容与该类有关,但又是独立于具体实例的存在。静态属性可以在任何位置被调用和修改,但是一旦被修改,所有的实例中调用的静态属性值都会产生变化。比如我们需要统计一共实例化了多少个Student类,就可以借助静态成员函数实现:

class Student
{public:int age;string name;static int number; // 申请number参数记录实例化的学生总数Student(){age=20;                                                                                                                                           name="ZhangSan";number++;}Student(int a,string b){age=a;name=b;number++;}
};
int Student::number=0; // 为静态属性赋初值,不符初值无法运行

测试一下:

int main()
{Student ZhangSan;cout<<ZhangSan.age<<" "<<ZhangSan.name<<" "<<ZhangSan.number<<endl;Student LiSi(25,"LiSi"); // 调用第二个构造函数(重载的构造函数)cout<<LiSi.age<<" "<<LiSi.name<<endl;cout<<LiSi.number<<" "<<ZhangSan.number<<" "<<Student::number<<endl; // 三种查看number的方法// 前两种查看方法是为了展示共享数据LiSi.number++; // 通过类的实例也可以修改静态属性或调用静态方法,但这并不符合静态属性的设计初衷,// 因此使用静态内容时最好用类进行引用,如下所示cout<<Student::number<<endl;
}
// 运行结果:20 ZhangSan 1
//         25 LiSi
//         2 2 2
//         3

除了静态属性,C++还有静态方法。静态方法只能访问静态属性和调用静态方法,但是非静态方法可以调用静态方法。依旧是一个简单的例子:

class Student
{public:int age;string name;Student(){age=20;                                                                                                                                           name="ZhangSan";}Student(int a,string b){age=a;name=b;}static void identity() // 用于展示这些学生的母校{cout<<"S University Student"<<endl;}
};

我们可以在主函数中调用静态方法:

int main()
{Student ZhangSan;ZhangSan.identity(); // 可以从实例中调用静态属性Student::identity(); // 也可以从类中直接调用
}
// 输出为:S University Student
//        S University Student

总结

这节我带大家入门了C++的面对对象编程,希望大家重点理解类和对象,掌握类的属性和方法的定义与调用,以及如何实例化,需要重点理解构造函数。析构函数、常成员函数和静态属性静态方法我们了解一下就好,至于公有和私有的概念,下一节还会重点讲解。

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

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

相关文章

C语言预备知识_hello world_数据类型_变量(入门到入神)

为什么要学习 C语言 学习 C语言是非常接近底层的一种编程语言C语言是学习其它编程语言第基础&#xff0c;基础不牢&#xff0c;地动山摇考研会用到 C语言 C语言预备知识 CPU 内存条 硬盘 显卡 主板 显示器之间的关系 当你在电脑上观看一部存储在硬盘上的电影时&#xff0c;各…

如何在 ChatGPT 上使用 Wolfram 插件回答数学问题

这里写自定义目录标题 写在最前面Wolfram是什么&#xff1f;ChatGPT 如何与 Wolfram 相结合&#xff0c;为什么有效&#xff1f;如何在 ChatGPT 上安装 Wolfram 插件&#xff1f; 写在最前面 参考&#xff1a;https://clickthis.blog/zh-CN/how-to-answer-math-questions-usin…

大一C语言查缺补漏 12.28

在C语言中&#xff0c;5%&#xff08;-3&#xff09;答案是什么 在C语言中&#xff0c;5 % -3的结果是2。因为在C语言中&#xff0c;取余运算&#xff08;%&#xff09;的结果的符号与被除数相同。所以&#xff0c;5 % -3的计算结果为2。 在C语言种引用数组元素时&#xff0c;其…

css、js、vue常考部分面试题

css css盒子水平垂直居中方法 方法一&#xff1a;定位 .child{height: 100px;position: absolute;//父元素相对定位top:50%;left:50%;transform: translate(-50%,-50%); } 方法二&#xff1a;定位 .child{width: 100px;height: 100px;position: absolute;top:50%;left:50%…

OVF简介(Open Virtualization Format:开放虚拟化格式 )

OVF&#xff08;Open Virtualization Format&#xff1a;开放虚拟化格式 &#xff09; 开源虚拟化格式OVF&#xff08;Open Virtualization Format&#xff09;文件是一种开源的文件规范&#xff0c;它描述了一个开源、安全、有效、可拓展的便携式虚拟打包以及软件分布格式。 …

Unity 使用Sprite绘制一条自定义图片的线

Unity 使用Sprite绘制一条自定义图片的线 前言项目场景布置代码编写总结 运行效果感谢 前言 遇到一个需要绘制自定义形状的需求。那只能利用Sprite来绘制一条具有自定义图片的线&#xff0c;通过代码动态设置起点、终点以及线宽&#xff0c;实现灵活的线条效果。 项目 场景…

c++属于同一个类的不同对象之间可相互访问private和protected成员

先看一个代码例子&#xff1a; #include <stdio.h>class A { private:char* name;void printA_Name() const {printf(name);} public:A(char* name) {this->name name;}void printA_Name(const A& a) {printf(a.name);}void printA_Name2(const A& a) {a.pr…

【Linux Shell】6. echo 命令

文章目录 【 1. 显示普通字符串 】【 2. 显示转义字符 】【 3. 显示变量 】【 4. 显示换行 】【 5. 显示不换行 】【 6. 显示命令执行结果 】 Shell 的 echo 指令用于字符串的输出。命令格式&#xff1a; echo string【 1. 显示普通字符串 】 #!/bin/bashecho "It is a …

arr.prototype 数组的方法

1.forEach 作用:遍历这个数组 代码&#xff1a; let arr [10, 20, 30, 40, 50];arr.forEach((item) > {console.log(item);}); 返回值:没有返回值 2.fiflter 作用:过滤数组 代码&#xff1a; let arr [10, 20, 30, 40, 50];let newArr arr.filter((item) > {retu…

机器学习(三) -- 特征工程(1)

系列文章目录 机器学习&#xff08;一&#xff09; -- 概述 机器学习&#xff08;二&#xff09; -- 数据预处理&#xff08;1-3&#xff09; 机器学习&#xff08;三&#xff09; -- 特征工程&#xff08;1-2&#xff09; 未完待续…… 目录 系列文章目录 前言 一、特征…

全视通-医院智能视讯系统 病房视讯系统解决方案 智能医院对讲系统信息发布系统

医院智能视讯系统解决方案 1、行业背景 对于患者来说现阶段各大医院的住院部大都面临同样的问题&#xff0c;例如患者就医缺乏精准化医疗&#xff0c;缺乏对患者的心理健康引导&#xff0c;缺乏多维度沟通渠道&#xff0c;缺乏多元增值服务等。 对于传统医院住院部病房&am…

JVM篇:字符串常量池

String类型字符串常量池问题 public class demo2 {public static void main(String[] args) {String s1 "a";String s2 "b";String s3 "ab";} } 对以上代码进行编译得到字节码文件后使用javap -c [字节码文件]反汇编得到以下信息 Constant…

自定义标记

章节目录&#xff1a; 一、概述二、使用自定义标记三、注册自定义标记3.1 创建文件3.2 修改文本编码格式 四、执行测试五、结束语 一、概述 pytest 可以支持自定义标记&#xff0c;自定义标记可以把一个 web 项目划分多个模块&#xff0c;然后指定模块名称执行。譬如我可以标明…

企业邮箱发送会议邀请:简单高效的邮件安排技巧与指南

通过电子邮件安排会议是工作中的常见做法。这也是确认口头安排的会议的一种有益方式。在本视频中&#xff0c;我们将详细介绍此类电子邮件的基本部分&#xff01; 您可能出于多种原因需要安排会议&#xff0c;例如安排面试、跟进业务主管或与潜在客户探讨项目。通过电子邮件有效…

HarmonyOS4.0系统性深入开发14AbilityStage组件容器

AbilityStage组件容器 AbilityStage是一个Module级别的组件容器&#xff0c;应用的HAP在首次加载时会创建一个AbilityStage实例&#xff0c;可以对该Module进行初始化等操作。 AbilityStage与Module一一对应&#xff0c;即一个Module拥有一个AbilityStage。 DevEco Studio默…

高并发如何保证接口的幂等性?

前言 接口幂等性问题&#xff0c;对于开发人员来说&#xff0c;是一个跟语言无关的公共问题。本文分享了一些解决这类问题非常实用的办法&#xff0c;绝大部分内容我在项目中实践过的&#xff0c;给有需要的小伙伴一个参考。 不知道你有没有遇到过这些场景&#xff1a; 有时我…

Open3D聚类算法

按照官网的例子使用聚类&#xff0c;发现结果是全黑的。 经过多次测试发现 eps3.3, min_points1这里是关键 min_points必须等于1否则无效果 import time import open3d as o3d; import numpy as np; import matplotlib.pyplot as plt#坐标 mesh_coord_frame o3d.geometry.Tria…

css sourcemap 源代码映射

vue.config.js css: {// Enable CSS source maps.sourceMap: process.env.NODE_ENV ! production, }重新运行&#xff1a;yarn serve 效果&#xff1a;

在目标检测中,Anchor的庞大数量使得存在严重的不平衡问题。这里的不平衡指的是什么。

问题描述&#xff1a; 在目标检测中&#xff0c;Anchor的庞大数量使得存在严重的不平衡问题。这里的不平衡指的是什么。 问题解答&#xff1a; 在目标检测任务中&#xff0c;Anchor指的是一组预定义的边界框或候选框&#xff0c;这些框以多个尺度和宽高比例组合而成。Anchor…

【Linux Shell学习笔记】Linux Shell基本流程和基本语法

第一部分&#xff1a;Linux Shell 简介 Shell 是一个用 C 语言编写的程序&#xff0c;它是用户使用 Linux 的桥梁。Shell 既是一种命令语言&#xff0c;又是一种程序设计语言。 Shell 是指一种应用程序&#xff0c;这个应用程序提供了一个界面&#xff0c;用户通过这个界面访问…