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

一、类的定义

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.hqwc.cn/news/472205.html

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

相关文章

压缩PDF的大小-Adobe Acrobat Pro

经常遇到上传的pdf太大&#xff0c;无法成功上传。 今天找到一个方法&#xff1a; 打开Adobe Acrobat Pro软件 → 文件 → 另存为其他&#xff08;H&#xff09;... →缩小大小的PDF 版本选择 4.0 最低的版本。 文件由9M变为1.5M。

第三百四十八回

文章目录 1. 概念介绍2. 使用方法2.1 List2.2 Map2.3 Set 3. 示例代码4. 内容总结 我们在上一章回中介绍了"convert包"相关的内容&#xff0c;本章回中将介绍collection.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在本章回中介绍的内容是col…

PLC_博图系列☞FBD

PLC_博图系列☞FBD 文章目录 PLC_博图系列☞FBD背景介绍FBD优势局限性 FBD 元素 关键字&#xff1a; PLC、 西门子、 博图、 Siemens 、 FBD 背景介绍 这是一篇关于PLC编程的文章&#xff0c;特别是关于西门子的博图软件。我并不是专业的PLC编程人员&#xff0c;也不懂电路…

anomalib1.0学习纪实

回顾&#xff1a;细分、纵深、高端、上游、积累、极致。 回顾&#xff1a;产品化&#xff0c;资本化&#xff0c;规模化&#xff0c;大干快上&#xff0c;小农思维必死无疑。 春节在深圳新地中央&#xff0c;学习anomalib1.0。 一、安装&#xff1a; 1、常规安装 采用的是…

Netty Review - 底层零拷贝源码解析

文章目录 Pre概述源码解析入口索引AbstractNioByteChannel.NioByteUnsafe#readallocHandle.allocate(allocator) 小结传统的零拷贝 Pre Netty Review - 直接内存的应用及源码分析 概述 Netty 的零拷贝技术是通过优化数据传输过程中的数据复制操作&#xff0c;以降低系统的开销…

租赁香港服务器多少钱一个月?24元

阿里云香港服务器2核1G、30M带宽、40GB ESSD系统盘优惠价格24元/月&#xff0c;288元一年&#xff0c;每月流量1024GB&#xff0c;多配置可选&#xff0c;官方优惠活动入口 https://t.aliyun.com/U/bLynLC 阿里云服务器网aliyunfuwuqi.com分享阿里云香港服务器优惠活动、详细配…

嵌入式Qt Qt中的字符串类

一.Qt中的字符串类 QString vs string&#xff1a; QString在Qt库中几乎是无所不在的 所有的Qt图形用户组件都依赖于QString 实验1 &#xff1a;QString 初体验 #include <QDebug> void Sample_1() {QString s "add";s.append(" "); // &q…

Python 异常处理及程序调试

Python 是一门功能强大而又易于学习的编程语言&#xff0c;它提供了丰富的工具和库来帮助开发者编写高效、稳定的程序。然而&#xff0c;在编写复杂的应用程序时&#xff0c;错误和异常是难以避免的。本文将介绍 Python 中的异常处理机制以及程序调试技巧&#xff0c;帮助读者提…

开什么店最稳定轻松?适合一个人开的实体店推荐

在创业的道路上&#xff0c;很多人都希望找到一种稳定轻松的开店方式。 作为一名资深的鲜奶吧创业者&#xff0c;我将分享我的经验和见解&#xff0c;希望能给那些想开实体店的朋友们一些启示&#xff01;&#xff01; 我开鲜奶吧已经有 5 年时间了&#xff0c;目前经营的是鲜…

Chat with RTX 安装

1、Chat With RTX 介绍 Chat With RTX 是一个 Demo&#xff0c;用来将您自己的资料&#xff08;文档、笔记、视频或其他数据&#xff09;与大语言模型建立连接&#xff0c;从而令 LLM 更具个性化。利用检索增强生成 (RAG)、TensorRT-LLM 和 RTX 加速&#xff0c;您可以与自定义…

Java实现河南软件客服系统 JAVA+Vue+SpringBoot+MySQL

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 系统管理人员2.2 业务操作人员 三、系统展示四、核心代码4.1 查询客户4.2 新增客户跟进情况4.3 查询客户历史4.4 新增服务派单4.5 新增客户服务费 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpringBootMySQL的河…

2022年12月电子学会青少年软件编程 中小学生Python编程等级考试二级真题解析(选择题)

2022年12月Python编程等级考试二级真题解析 选择题&#xff08;共25题&#xff0c;每题2分&#xff0c;共50分&#xff09; 1、运行下列程序&#xff0c;最终输出的结果是 info {1:小明,2:小黄,3:小兰} info[4]小红 info[2]小白 print(info) A、{1:小明,2:小白,3:小红,4:小…