【C++】---类和对象(上)入门

news2024/11/28 7:26:20

一、类的定义

1.那么众所周知,C语言是面向过程的,关注的是过程,分析出求解的步骤,通过函数的调用来逐步解决问题
2.而C++是基于面向对象的,关注的是对象将一件事情拆分成不同的对象,靠对象之间交互完成!

class classname
{
	// 类体:由 成员变量 和 成员函数 组成

};// 一定要注意后面的分号

3.class是定义类的关键字classname是类的名字{}中的为类的主体,注意:类结束时后面的分号不能省略
4.类中的内容:称为类的成员:类中的变量称为成员变量或者类的属性。类中的函数称为成员函数或者类的方法。

二、类的访问限定符和封装

1.类的访问限定符

对象的属性(变量)和方法(函数)结合在一起,让对象更加完善
通过访问权限选择性的将类的接口提供给外部用户进行访问使用
C++的访问限定符分为以下几种:

  1. public:被public修饰的成员在类外可以直接被访问
  2. protected和private:被protected和private所修饰的成员在类外不能被直接访问!(此处protected和private是类似的)
  3. 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
  4. 如果后面没有访问限定符,作用域就到 } 即类结束。
  5. class的默认访问权限为privatestruct为的默认访问权限public(因为struct要兼容C)
    注意:访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别
    问题:C++中struct和class的区别是什么?
    解答:C++需要兼容C语言,所以C++中struct可以当成结构体使用。另外C++中struct还可以用来
    定义类
    。和class定义类是一样的,区别是struct定义的类默认访问权限是public,class定义的类
    默认访问权限是private
    。注意:在继承和模板参数列表位置,struct和class也有区别,后序给大
    家介绍。

2.类的封装

面向对象的三大特性:封装、继承、多态
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来
和对象进行交互。

封装本质上是一种管理,让用户更方便使用类。比如:对于电脑这样一个复杂的设备,提供给用
户的就只有开关机键、通过键盘输入,显示器,USB插孔等,让用户和计算机进行交互,完成日
常事务。但实际上电脑真正工作的却是CPU、显卡、内存等一些硬件元件。
在这里插入图片描述
在这里插入图片描述
封装使面向对象更严格、更规范。

三、类的作用域

类定义了一个新的作用域,类的所有成员都在类的作用域中。在类体外定义成员,需要使用 :: 作用域解析符指明成员属于哪个类域。整个域是一个整体,成员变量无论在成员函数上面或者下面都可以进行访问。

#include<stdlib.h>
#include<iostream>
using namespace std;
typedef int STDataType;
 
class Stack
{
public:
	//初始化
	void StackInit(int initSize);
	
public:
	STDataType* a;
	int size;
	int capacity;
 
};
 
//指明成员属于Stack类
void Stack::StackInit(int initSize = 4)
{
		a = (STDataType*)malloc(sizeof(STDataType) * 4);
		size = 0;
		capacity = initSize;
}

四、类的实例化

1.什么是类的实例化

什么是类的实例化?
用 类 创建 对象 的过程!

2.为什么要对类进行实例化?

1.类是对 对象描述的一个东西一个模板,就是一个空壳。这里面只限定了类有哪些成员,定义出了一个类,但是并没有分配实际的空间来储存它。
(就比如说:入学时填的学生信息表,那个学生信息表的表格就是一个类,它就相当于一个空壳
2.一个类可以实例化出多个对象,实例化出的对象 占用实际的物理空间,存储类成员变量

3.具体理解实例化

在这里插入图片描述
在这里插入图片描述
实例:

#include <stdlib.h>
#include<iostream>
using namespace std;
 
typedef int STDataType;
 
struct Stack
{
	//初始化
	void StackInit(int initSize = 4)
	{
		a = (STDataType*)malloc(sizeof(STDataType) * 4);
		size = 0;
		capacity = initSize;
	}
 
	STDataType* a;
	int size;
	int capacity;
 
};
 
int main()
{
	
	Stack st; //实例化对象
 
    return 0;
}

4.对定义的深刻理解

注意:对变量定义成功的标志:该变量在内存中开了空间


class Date
{
//private:
public:
	int _year;//这里对变量只是声明!!!声明不开辟空间!
	int _month;//注意:对变量定义成功的标志:该变量在内存中开了空间
	int _day;

public:
	void Init(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}

	void Print()
	{
		cout << _year << "/" << _month << "/" << _day << endl;
	}

};

int main()
{
	//Date D1;//此处对类进行了定义!
	D1._year;//为啥不能访问?因为:_year没有定义

	return 0;
}

五、类对象模型

1.如何计算类的大小

1.遵循内存对齐原则
我们直接通过上实例代码进行理解:

//既有 成员函数 又有 成员变量
class A1
{
public:
	void f1(){}

private:
	int _a;
};
//只有 成员函数
class A2
{
public:
	void f2(){}
};
//空类
class A3
{

};
int main()
{


	cout << sizeof(A1) << endl;
	cout << sizeof(A2) << endl;
	cout << sizeof(A3) << endl;

	return 0;
}

在这里插入图片描述
C++规定:没有成员变量的类对象,它的大小为1字节,占位标识类存在过
结论:一个类的大小,实际就是该类中”成员变量”之和,当然要注意内存对齐
注意:空类的大小,空类比较特殊,编译器给了空类1个字节来唯一标识这个类的对象。

  • 第一个成员在与结构体偏移量为0的地址处。
  • 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。注意:对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值,VS中默认的对齐数为8
  • 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍
  • 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

2.类的对象储存方式

假如对象中包含类的各个成员,既包含成员变量,又包含成员函数,由于每个对象中成员变量是不同的,但调用的是同一份成员函数,如果按照此种方式存储,当一个类创建多个对象时,每个对象中都会保存一份成员函数代码,相同代码保存多次,会浪费空间。
在这里插入图片描述

因此C++采用类对象中只存储成员变量成员函数存放在公共代码段中的方式来存储类的对象。
在这里插入图片描述

//既有 成员函数 又有 成员变量
class A1
{
public:
	void f1(){}

private:
	int _a;
};
//只有 成员函数
class A2
{
public:
	void f2(){}
};
//空类
class A3
{

};
int main()
{
	A1 a1;
	A2 a2;
	A3 a3;
	cout << sizeof(A1) << endl;
	cout << sizeof(A2) << endl;
	cout << sizeof(A3) << endl;

	cout << &a1 << endl;
	cout << &a2 << endl;
	cout << &a3 << endl;

	return 0;
}

在这里插入图片描述
尽管对象a2的类中没有成员变量仅有成员函数,对象a3的类中既没有成员变量也没有成员函数,但是它们的地址不同,表明对象a2和对象a3存在过。

六、this指针

1.this指针引出

我们先来定义一个日期类 Date:

class Date
{ 
public:
 void Init(int year, int month, int day)
 {
 _year = year;
 _month = month;
 _day = day;
 }
 void Print()
 {
 cout <<_year<< "-" <<_month << "-"<< _day <<endl;
 }
 private:
 int _year;     // 年
 int _month;    // 月
 int _day;      // 日
};
int main()
{
 Date d1, d2;
 d1.Init(2022,1,11);
 d2.Init(2022, 1, 12);
 d1.Print();
 d2.Print();
 return 0;
}

对于上述类,有这样的一个问题:
Date类中有 Init 与 Print 两个成员函数,函数体中没有关于不同对象的区分,那当d1调用 Init 函数时,该函数是如何知道应该设置d1对象,而不是设置d2对象呢?
C++中通过引入this指针解决该问题,即:C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量”的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成

2.this指针的特性

  1. this指针的类型:类类型 const*,即成员函数中,不能给this指针赋值。(但是可以给指针所指向的内容进行赋值)
  2. 只能在“成员函数”的内部使用
  3. this指针本质上是“成员函数”的形参(存放在栈区),当对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针
  4. this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递

(1)例如:如果定义两个对象,d1和d2如何访问自己的年月日呢?两个对象调用的是同一份成员函数,如何做到各自初始化各自的?

#include <iostream>
using namespace std;

class Date
{
private:
	int _year;
	int _month;
	int _day;
public:
	void Print()
	{
		cout << _year << "/" << _month << "/" << _day << endl;
	}
	void Init(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
};

int main()
{
	Date d1;
	Date d2;
	d1.Init(2024, 2, 15);
	d2.Init(2024, 2, 16);

	d1.Print();
	d2.Print();
	return 0;
}

在这里插入图片描述

因为编译器做了处理,Init函数的入参不是3个参数,实际上是4个参数,编译器会增加一个隐含的参数:this指针,编译器会把对象的地址传给this

int main()
{
	Date d1;
	d1.Init(2024, 2, 15);//实际为d1.Init(&d1,2024,2,15)
 
	Date d2;
	d2.Init(2024, 2, 16);//实际为d2.Init(&d2,2024,2,16)
 
    return 0;
}

编译器增加的隐含的this指针参数,即void Init(Date* this, int year, int month, int day),作为形参,this指针存在于栈中。

3.两个例题充分理解

1.下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行

// 1.下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行
class A
{
比特就业课
8.3. C语言和C++实现Stack的对比
1. C语言实现
public:
 void Print()
 {
 cout << "Print()" << endl;
 }
private:
 int _a;
};
int main()
{
 A* p = nullptr;
 p->Print();
 return 0;
}

这里变量p是一个类的指针,把它置为nullptr,然后把它当做指针,赋给this指针,在语法上并没有错误所以不会编译出错,然后访问函数Print,但是访问的时候,他并没有对this指针所指向的内容进行解引用(访问)
所以:选C

2.下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行

// 1.下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行
class A
{ 
public:
    void PrintA() 
   {
        cout<<_a<<endl;
   }
private:
 int _a;
};
int main()
{
    A* p = nullptr;
    p->PrintA();
    return 0;
}

这里调用了函数,打印a,就着nullptr作为形参传递给this指针,进行解引用,就会运行崩溃!!!

好了,今天的分享就到这里了
如果对你有帮助,记得点赞👍+关注哦!
我的主页还有其他文章,欢迎学习指点。关注我,让我们一起学习,一起成长吧!
在这里插入图片描述

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

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

相关文章

【自然语言处理】:实验1布置,Word2VecTranE的实现

清华大学驭风计划 因为篇幅原因实验答案分开上传&#xff0c;答案链接http://t.csdnimg.cn/5cyMG 如果需要详细的实验报告或者代码可以私聊博主 有任何疑问或者问题&#xff0c;也欢迎私信博主&#xff0c;大家可以相互讨论交流哟~~ 实验1&#xff1a; Word2Vec&TranE的…

使用HTML、CSS和JavaScript构建响应式企业官网

使用HTML、CSS和JavaScript构建响应式企业官网&#xff0c;web网页设计与制作-htmlcssjs实现企业官网展示。 页面效果展示 pc端和移动端 动态演示 文件目录 assets文件夹&#xff1a;静态资源目录&#xff0c;主要存放css、fonts、images、js等静态资源文件&#xff1b; fa…

Unity如何修改预制体(预制件)?

文章目录 19 复制复制复制&#xff0c;预制体与变体 19 复制复制复制&#xff0c;预制体与变体 【预制件】 预制件作用&#xff1a;方便复用 【预制件】的制作 直接拖拽&#xff0c;从层级面板 -> 项目面板。层级面板中当前图标会变蓝&#xff0c;子物体名字变蓝色。预制件…

《PCI Express体系结构导读》随记 —— 第II篇 第13章 PCI总线与虚拟化技术(5)

接前一篇文章&#xff1a;《PCI Express体系结构导读》随记 —— 第II篇 第13章 PCI总线与虚拟化技术&#xff08;4&#xff09; 13.1 IOMMU 13.1.3 AMD处理器的IOMMU AMD处理器的IOMMU技术与Intel的VT-d技术类似&#xff0c;其完成的主要功能也类似。AMD率先提出了IOMMU的概念…

(11)Hive调优——explain执行计划

一、explain查询计划概述 explain将Hive SQL 语句的实现步骤、依赖关系进行解析&#xff0c;帮助用户理解一条HQL 语句在底层是如何实现数据的查询及处理&#xff0c;通过分析执行计划来达到Hive 调优&#xff0c;数据倾斜排查等目的。 官网指路&#xff1a; https://cwiki.ap…

【网站项目】228高校教师电子名片系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

Vi 和 Vim 编辑器

Vi 和 Vim 编辑器 vi 和 vim 的基本介绍 Linux 系统会内置 vi 文本编辑器 Vim 具有程序编辑的能力&#xff0c;可以看做是 Vi 的增强版本&#xff0c;可以主动的以字体颜色辨别语法的正确性&#xff0c;方便程序设计。 代码补完、编译及错误跳转等方便编程的功能特别丰富&…

智慧供应链控制塔大数据解决方案

一、供应链控制塔的概念定义 (1) Gartner 的定义: “控制塔是一个物理或虚拟仪表板,提供准确的、及时的、完整的物流事件和数据,从组织和服务的内部和跨组织运作供应链,以协调所有相关活动。”、“供应链控制塔…提供供应链端到端整体可见性和近实时信息和决策的概念……

基于PSO优化的LSTM多输入分类(Matlab)粒子群优化长短期神经网络分类

目录 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 亮点与优势&#xff1a; 二、实际运行效果&#xff1a; 三、部分代码展示&#xff1a; 四、完整代码数据分享下载&#xff1a; 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 本代码基于Matal…

数据库第二次实验

目录 1 实验内容 2 SQL代码及运行截图 2.1 创建表并插入数据 2.1.1 创建表 2.1.2 插入数据 2.1.3 运行截图 2.2 修改表 2.2.1 SQL代码 2.2.2 运行截图 2.3 删除操作 2.3.1 SQL代码 2.3.2 运行截图 2.4 数据库的备份 2.5 数据库的恢复 1 实验内容 实验目的&#…

暴力枚举刷题1

题目来源&#xff1a;统计方形&#xff08;数据加强版&#xff09; - 洛谷 参考书籍&#xff1a;《深入浅出程序设计竞赛&#xff08;基础篇&#xff09;》 解题思路&#xff1a;这道理适合用暴力枚举求解。我把书上提到的四种枚举方法分享给大家。 解题1&#xff1a;减少枚…

【AI绘画】硬核解读Stable Diffusion(完整版) 小白必收藏!!!

手把手教你入门绘图超强的AI绘画&#xff0c;用户只需要输入一段图片的文字描述&#xff0c;即可生成精美的绘画。给大家带来了全新保姆级教程资料包 &#xff08;文末可获取&#xff09; 2022年可谓是AIGC&#xff08;AI Generated Content&#xff09;元年&#xff0c;上半年…

C# CAD SelectionFilter下TypedValue数组

SelectionFilter是用于过滤AutoCAD实体的类&#xff0c;在AutoCAD中&#xff0c;可以使用它来选择具有特定属性的实体。构造SelectionFilter对象时&#xff0c;需要传入一个TypedValue数组&#xff0c;它用于定义选择规则。 在TypedValue数组中&#xff0c;每个元素表示一个选…

【制作100个unity游戏之25】3D背包、库存、制作、快捷栏、存储系统、砍伐树木获取资源、随机战利品宝箱7(附带项目源码)

效果演示 文章目录 效果演示系列目录前言新增简单的泛型单例消耗品源码完结 系列目录 前言 欢迎来到【制作100个Unity游戏】系列&#xff01;本系列将引导您一步步学习如何使用Unity开发各种类型的游戏。在这第25篇中&#xff0c;我们将探索如何用unity制作一个3D背包、库存、…

HTML5+CSS3+JS小实例:锥形渐变彩虹按钮

实例:锥形渐变彩虹按钮 技术栈:HTML+CSS+JS 效果: 源码: 【HTML】 <!DOCTYPE html> <html lang="zh-CN"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /…

无人机导航技术,无人机导航理论基础,无人机导航技术应用发展详解

惯性/卫星定位组合是一种比较理想的组合导航系统。在无人机导航领域&#xff0c;多年来惯性/卫星定位组合导航系统的研究一直受到普遍的关注&#xff0c;大量的理论研究成果得到实际应用。 常见的几类导航系统 单一导航 卫星导航系统 、多普勒导航、惯性导航系统(INS) 、图形…

【知识整理】产研中心岗位评定标准之大数据岗位

为贯彻执行集团数字化转型的需要,该知识库将公示集团组织内各产研团队不同角色成员的职务“职级”岗位的评定标准; 一、定级定档目的 通过对公司现有岗位及相应岗位员工的工作能力、工作水平进行客观公正评定,确定各岗位的等级及同等级岗位员工对应的档级,从而为员工以后的晋升…

【Cocos入门】物理检测

目录 一、物理检测的概念二、点测试三、矩形测试四、射线测试 一、物理检测的概念 CoCos中&#xff0c;物理检测也是物理系统的一部分&#xff0c;它不是用于检测物体的物理特性的&#xff0c;而是用来查询物体的(比如某个地方是否存在物理碰撞体)。其又分成&#xff1a;点检测…

Mysql运维篇(四) Xtarbackup--备份与恢复练习

一路走来&#xff0c;所有遇到的人&#xff0c;帮助过我的、伤害过我的都是朋友&#xff0c;没有一个是敌人。如有侵权&#xff0c;请留言&#xff0c;我及时删除&#xff01; 前言 xtrabackup是Percona公司CTO Vadim参与开发的一款基于InnoDB的在线热备工具&#xff0c;具有…

【PyQt】11-QTextEdit、QPushButton

文章目录 前言一、文本输入-QTextEdit1.1 代码1.2 运行结果 二、QPushButton2.1.1 按钮上添加文本2.1.2 按键的弹跳效果2.1.3 两个信号可以绑定一个槽。2.1.4 带图标的按键运行结果 2.1.5 按键不可用以及回车默认完整代码2.2 单选按键控件运行结果 2.3 复选框&#xff08;多选框…