C++的类和对象(一)

目录

1、面向过程和面向对象初认识

2、为什么要有类 

3、类的定义 

类的两种定义方式 

4、类的访问限定符

5、类的作用域

5.1 为什么要有作用域?

5.2类作用域

6、类的实例化

6.1类的实例化的定义 

 6.2类的实例化的实现

 6.3经典面试题

7、类对象

7.1类对象的大小计算

 7.2类对象的存储方式猜测

8、this指针 

8.1this指针的介绍 

8.2this指针的特性 


1、面向过程和面向对象初认识

C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。
C++是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。
就拿外卖来举例:

面向过程关注的就是:客户下单、店家接单、骑手送餐,这三个的过程

面向对象关注的就是:店家、骑手、客户,这三者之间的关系

注意:C++是基于面向对象,不是纯面向对象,也可以面向过程

2、为什么要有类 

在C语言中已经有结构体了,为什么还要设计一个类出来呢?

在C语言中结构体只能用来定义变量,C++中对结构体进行了延伸,不仅可以用来定义变量还可以用来定义函数,而C++更喜欢用class来代替struct,也就是我们经常说的类,并且C++中类的功能可比C语言的结构体强大太多了。面向对象的三大特性:封装、继承、多态,都需要用到类来实现。

3、类的定义 

class Student
{
public:
	void PrintInfo()//成员函数
	{
		cout << name << " " << sex << " " << age << endl;
	}

	char name[10];//成员变量
	char sex[3];
	int age;
};//和结构体一样最后也是要带上分号的

class为定义类的关键字;Student为类名;public为类的访问限定符,一共有三个,后面会讲到;{}里面为类的主体。

类中的元素称为类的成员:类中的数据称为类的属性或者成员变量; 类中的函数称为类的方法或者成员函数。 

类的两种定义方式 

1、声明和定义全部放到类体中,注意:如果成员函数在类中定义,可能会被编译器当成内联来处理

2、声明放到.h文件中,定义放到.cpp文件中,实现声明和定义的分离

我们一般在做项目的时候都比较建议采用第二种。

4、类的访问限定符

  1. public修饰的成员在类外可以直接被访问。
  2. protected和private修饰的成员在类外不能直接被访问。
  3. 访问权限作用范围从该访问限定符出现的位置开始直到下一个访问限定符出现时为止,如果没有下一个访问限定符的出现,那么就一直到 } 类结束。
  4. class的默认访问权限为private。

 注意访问限定符只在编译时有用,当数据保存到内存后,没有任何访问限定符的区别。

经典面试题

C++中struct和class的区别是什么?

C++是兼容C的,所以C++中的struct也可以当成结构体用,还可以用来定义类来使用,和class是一样的,但是struct定义的类的默认访问权限是public,class的默认访问权限是private

5、类的作用域

5.1 为什么要有作用域?

作用域是为了避免变量名冲突和提供代码的组织结构而存在的。作用域定义了一个变量或函数在程序中的可见范围。例如,如果有两个变量具有相同的名称,但它们位于不同的作用域内,它们就不会相互干扰。作用域可以分为全局作用域和局部作用域,全局作用域表示变量或函数在程序中的任何位置都可以访问,而局部作用域表示变量或函数仅在限定的代码块或函数内可见。通过使用作用域,程序员可以更好地控制代码,并减少错误和混淆。

5.2类作用域

类定义了一个新的作用域,类的所有成员都在类的作用域中。在类体外定义成员时,需要使用类名+ ::(作用域操作符)来指明成员属于哪个类域。

6、类的实例化

6.1类的实例化的定义 

在C++中,类的实例化指的是使用类定义创建类的一个实例(也称为对象)。当定义一个类时,只是定义了类的结构和属性,但是没有实际的实例存在。为了使用类,必须先创建一个实例,然后可以使用该实例调用类中的方法和访问其属性。

 6.2类的实例化的实现

class Student
{
public:
	void PrintInfo();
private:
	char name[10];        
	char sex[3];
	int age;
};

int main()
{
	Student s;//实例化出一个对象
	s.PrintInfo();//用实例化出的对象访问类中的成员
	return 0;
}

 实例化出的对象只能访问public修饰的成员,protected和private修饰的就访问不了。

 和C语言的结构体一样也是用.进行访问。

一个类可以实例化出多个对象,实例化出的对象占用实际的物理空间,存储类成员变量。

 6.3经典面试题

 了解完类的实例化后,看一下下面的题你是否能做出来

int age;//声明 or 定义?

class Student
{
public:
	void PrintInfo();

	char name[10];
	char sex[3];
	int age;//声明 or 定义?
};

 上面两个age一个在全局中,一个在类中,且都是在.h文件中,他们是声明还是定义?

当你编译的时候很可能会出现这样链接错误。

 先要明白的概念

  1. 声明和定义的区别就在于开没开空间。
  2. 类在没有实例化之前是不占用空间的,只有实例化出对象了才占用空间

打个比方:类实例化出对象就像现实中使用建筑设计图盖房子,类就像是设计图,只设计出需要什么东西,但是并没有实体的建筑存在,同样类也只是一个设计,实例化出的对象(房子)才能实际存储数据,占用物理空间

解答:

  • 全局的age是定义, 类中的age是声明。
  • 链接冲突是因为你是在.h中定义的,.h文件内容最终会在.cpp文件中展开,全局age是定义,当有多个.cpp文件同时编译完后在合成一个目标文件时,多个.cpp文件中都定义了同一个age就会造成冲突

要想解决这个问题可以在全局的age前面加上extern或者static

  • extern是用于声明在另一个文件或模块中定义的变量或函数的关键字。当变量或函数声明为extern时,它告诉编译器该符号在其他地方定义,应该在链接期间解析。这允许函数和变量在程序中的多个文件或模块之间共享。
  • 加static只在当前文件可见,链接属性不一样

7、类对象

7.1类对象的大小计算

// 类中既有成员变量,又有成员函数
class A1 {
public:
	void f1() {}
private:
	char c;
	int a;
};
//类中仅有成员变量
class A2
{
private:
	int a;
};
// 类中仅有成员函数
class A3 {
public:
	void f2() {}
};
//空类
class A4
{};

用sizeof计算他们的大小结果为sizeof(A1):8, sizeof(A2):4,sizeof(A3):1,sizeof(A4):1。

从结果可以看出类的大小的计算也是要遵守结构体内存对齐规则。并且成员函数是不占大小的,空类也是给了1字节的

空类给这1字节的目的是为了占位,占位不存储实际数据,是为了表识对象的存在。

 7.2类对象的存储方式猜测

1. 对象中包含类的各个成员

每个对象中都包含类的各个成员,但是这样缺点很明显,每个对象中成员变量是不同的,但是调用同一个函数,如果按照这种方式存储,当一个类创建多个对象时,每个对象中都会保存一份相同的代码,浪费空间。

2.代码只保存一份,在对象中保存存放代码的地址

 这个方式在多态下会被采用

3.只保存成员变量,成员函数存放在公共的代码段

 这种方式在编译连接时就会根据函数名去公共代码区找到函数的地址,call 函数的地址

 

8、this指针 

8.1this指针的介绍 

this指针是指向当前对象的指针。在C++中,每个对象都有一个指向自身的this指针,这样当有多个对象调用成员函数时就可以做到区分作用。

当在类的成员函数内部访问“非静态的”对象的成员变量或成员时,C++编译器会自动将该对象的地址赋给this指针,以便在函数内部可以通过this指针来访问对象的成员,这些操作对用户是隐藏的,即用户不需要来传递,编译器自动完成。

例如:

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

int main()
{
	Date d1;
	Date d2;
	d1.Init(2023, 11, 10);
	d2.Init(2023, 11, 11);
	d1.Print();
	d2.Print();
	return 0;
}

在上述示例中,Init()和Print()两个成员函数内部都使用了this指针来访问成员变量,在传参的时候编译器隐藏了this指针,不需要用户手动去传的

void Init(Date * const this, int year, int month, int day)
	{
		this->_year = year;
		this->_month = month;
		this->_day = day;
	}
d1.Init(&d1, 2023, 11, 10);

 上面的示例是一个伪代码。

实参和形参位置不能显示传递和接收this指针,但是可以在成员函数内部使用this指针。 

8.2this指针的特性 

  • this指针的类型是*const的,const出现在星号右边,表示指针本身是常量,不能给this指针赋值即const pointer,non-const data。
  • 只能在成员函数的内部使用。
  • this指针本质上是成员函数的形参,当对象调用成员函数时,将对象地址作为实参传递给this形参。但是对象中不存储this指针。
  • this指针是成员函数第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递。
  • this指针是存放在栈上的,因为它是个形参;但是不同的编译器可能会做优化,像VS编译器就是存放在寄存器上的,速度更快。
  • this指针可以为空。例如下面例子就是可以正常运行的
class Date
{
public:
	void Print()
	{
		cout << this << endl;
		cout << "hello Date" << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date* d1 = nullptr;
	d1->Print();//正常运行
	return 0;
}

运行结果

因为它没有对this指针进行使用操作,所以它是正常运行的。

但是下面这个代码就是运行崩溃

class Date
{
public:
	void Print()
	{
		cout << _year << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date* d1 = nullptr;
	d1->Print();//运行崩溃
	return 0;
}

this指针为空,使用了一个空指针去访问成员变量,很明显是空指针问题,所以会运行崩溃。

这两份代码,一个对this指针进行了使用,一个没有,所以结果也会不同。 


如果有写的不好或不对的地方欢迎大家指正。谢谢!!!
 

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

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

相关文章

QT 中使用 QTableView 和 QStandardItemModel 实现将数据导出到Excel 和 从Excel导入到 QTableView 的功能

简介 在Qt中&#xff0c;使用QTableView和QStandardItemModel来实现将数据导出到Excel和从Excel导入到QTableView的功能&#xff0c;而不使用第三方库&#xff08;如QXlsx&#xff09;。 效果 将 QTableView 中的数据导出到Excel //从tableview 导出到 EXcle void MainInterfa…

CSS BFC特性和应用

目录 1&#xff0c;介绍2&#xff0c;BFC布局规则3&#xff0c;创建BFC4&#xff0c;BFC应用1&#xff0c;浮动子元素使父级高度坍塌2&#xff0c;非浮动元素被浮动元素覆盖3&#xff0c;margin 合并1&#xff0c;父子 margin 合并&#xff1a;父级和第1个/最后1个子元素2&…

Ubuntu 安装 MySQL8 配置、授权、备份、远程连接

目录 0100 系统环境0200 下载0300 安装0400 服务管理0401 关闭、启动、重启服务0402 查看服务状态 0500 查看配置文件0600 账号管理0601 添加账号0602 删除账号0603 修改密码0604 忘记root密码 0700 自动备份0800 远程访问 0100 系统环境 [rootlocalhost ~]# cat /proc/versio…

SQL Server数据库部署

简介 21世纪&#xff0c;人类迈入了“信息爆炸时代”&#xff0c;大量的数据、信息在不断产生&#xff0c;伴随而来的就是如何 安全、有效地存储、检索和管理它们。对数据的有效存储、高效访问、方便共享和安全控制已经成 为信息时代亟待解决的问题。数据库&#xff08;Databas…

锐捷RG-UAC应用网关 前台RCE漏洞复现

0x01 产品简介 锐捷RG-UAC系列应用管理网关是锐捷自主研发的应用管理产品。 0x02 漏洞概述 锐捷RG-UAC应用管理网关 nmc_sync.php 接口处存在命令执行漏洞&#xff0c;未经身份认证的攻击者可执行任意命令控制服务器权限。 0x03 复现环境 FOFA&#xff1a;app"Ruijie-R…

〖大前端 - 基础入门三大核心之JS篇㊹〗- DOM事件委托

说明&#xff1a;该文属于 大前端全栈架构白宝书专栏&#xff0c;目前阶段免费&#xff0c;如需要项目实战或者是体系化资源&#xff0c;文末名片加V&#xff01;作者&#xff1a;不渴望力量的哈士奇(哈哥)&#xff0c;十余年工作经验, 从事过全栈研发、产品经理等工作&#xf…

认识K线形态,把握买入卖出时机

一、认识K线 1、K线的含义 股票一天之内有4个最关键的价格&#xff0c;开盘价、收盘价、最高价和最低价&#xff0c;把这个价格显示在图上就是K线图。 以金斗云智投电脑版为例&#xff0c;打开软件&#xff0c;任意搜索一支个股&#xff0c;就可以看到这支股票的K线。 股市新…

智加科技获全国首张重卡无人驾驶开放道路测试牌照

2023年12月1日&#xff0c;智加科技获得苏州市智能网联汽车无人化测试牌照。该牌照也是江苏省及国内首张无人重卡开放高速公路全路段全场景全息路网&#xff08;S17苏台高速&#xff09;道路测试牌照。 该重卡无人驾驶开放道路测试牌照&#xff0c;经由苏州市智能网联汽车联席小…

假设检验和统计推断:从样本到总体

1. 写在开头 统计学中的假设检验和统计推断是从样本数据中对总体进行推断和判断的关键工具。本文将深入探讨假设检验的类型,并结合具体的场景和例子,展示不同类型假设检验的应用。 2. 单样本 t 检验 2.1 概述 单样本 t 检验(One-sample t-test)是一种用于比较一个样本的…

Asp.net core WebApi 配置自定义swaggerUI和中文注释,Jwt Bearer配置

1.创建asp.net core webApi项目 默认会引入swagger的Nuget包 <PackageReference Include"Swashbuckle.AspNetCore" Version"6.2.3" />2.配置基本信息和中文注释&#xff08;默认是没有中文注释的&#xff09; 2.1创建一个新的controller using Micr…

卷积神经网络-3D医疗影像识别

文章目录 一、前言二、前期工作1. 介绍2. 加载和预处理数据 二、构建训练和验证集三、数据增强四、数据可视化五、构建3D卷积神经网络模型六、训练模型七、可视化模型性能八、对单次 CT 扫描进行预测 一、前言 我的环境&#xff1a; 语言环境&#xff1a;Python3.6.5编译器&a…

Mongodb安装及其使用

1.Linux系统上安装Mongodb 在usr/local文件夹下创建mongo文件夹 下载mongodb包 wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-6.0.5.tgz解压mongodb tar -zxvf mongodb-linux-x86_64-rhel70-6.0.5.tgz更改文件夹的名字 mv mongodb-linux-x86_64-rh…

竞赛选题 题目:基于深度学习的手势识别实现

文章目录 1 前言2 项目背景3 任务描述4 环境搭配5 项目实现5.1 准备数据5.2 构建网络5.3 开始训练5.4 模型评估 6 识别效果7 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于深度学习的手势识别实现 该项目较为新颖&#xff0c;适合作为竞赛课题…

1.3 Linux文件系统

一、Linux文件系统结构 Linux下都是文件&#xff0c;所以没有Windows一样的盘&#xff0c;有的只有文件夹。 cd /    // 进入根目录 ls     // 查看根目录"/"下的文件及文件夹 /bin    &#xff1a;存储了很多系统命令&#xff0c; /usr/sbin 也存储了…

数据库表的管理

表的基本概念 表是包含数据库中所有数据的数据库对象。数据在表中的组织方式与在电子表格中相似&#xff0c;都是 按行和列的格式组织的。每行代表一条唯一的记录&#xff0c;每列代表记录中的一个字段。例如&#xff0c;在包含公 司员工信息的表中&#xff0c;每行代表一名员工…

Python zip函数及用法与lambda表达式及用法

Python zip函数及用法 zip() 函数可以把两个列表“压缩”成一个 zip 对象&#xff08;可迭代对象&#xff09;&#xff0c;这样就可以使用一个循环并行遍历两个列表。为了测试 zip() 函数的功能&#xff0c;我们可以先在交互式解释器中“试验”一下该函数的功能。 >>&g…

群晖Video Station 添加海报墙-新方法

海报墙 一般我们找到的都是mp4、mkv等格式的视频资源&#xff0c;而没有像上图这样的海报资源&#xff0c;那要怎样实现海报墙呢&#xff1f; 按照以前的方法&#xff0c;是可以通过The Movie Database的API Key来搜刮电影海报信息&#xff0c;但是现在这个方法不行了 现在介绍…

力扣66. 加一

文章目录 力扣66. 加一示例代码实现总结收获 力扣66. 加一 示例 代码实现 class Solution {public int[] plusOne(int[] digits) {int ndigits.length;for(int in-1;i>0;i--){if(digits[i]!9){digits[i];for(int ji1;j<n;j){digits[j]0;}return digits;}}int[] resnew i…

使用String.valueOf()的坑

说明&#xff1a;记录一次使用String.valueOf()的坑&#xff0c;以下是一段有问题的代码&#xff1a; String count String.valueOf(listData.get(0).get(0).get("count");if (StringUtils.isBlank(count) || "0".equals(count)) {result.setResult(page)…
最新文章