C++的类

news/2024/11/22 9:10:38/

文章目录

  • class定义类
    • 声明和定义不分离
    • 成员函数声明与定义的分离
  • 类的访问限定符
  • 类的实例化
  • 类对象的大小
  • this指针

引入:什么是类呢?
在C语言阶段,结构体成员只能是它的属性,这个结构体就相当于张三,小时候它只被赋予了名字,性别,家庭住址等属性,但是他没有去做某件事的能力,而C++中呢就相当于他长大了,就可以有骑车,跑步,和别人聊天的能力,这种既可以包含属性,又可以有某些行为的,我们就称它为类。
在C++中我们选择用关键字class来代替struct,当然struct也是可以继续用的

class定义类

类的定义有两种方式,一种是定义和声明都放在类体中,另一种是声明和定义分离分别放在.h和.cpp中

声明和定义不分离

在这里插入图片描述

成员函数声明与定义的分离

我们把结构体,类等放在头文件.h其中之一的目的就是为了方便我们去看,这个类的功能,那么当成员函数的声明与定义都放在头文件.h中时,未免就会造成头文件代码过多,不容易查看。此时我们就要让声明与定义分离,把成员函数的定义放到.cpp文件中,但是要加上类域,不然编译器就会分不清这个函数到底是普通函数还是成员函数。
例如上述代码成员函数定义在.cpp文件中就要这样写:
在这里插入图片描述

在这里插入图片描述
要指明类域且返回类型放在最前面。
如果成员函数是内联函数,那么它的声明与定义就不能分离,所以它的定义要定义在头文件中和声明放在一起。
成员函数直接定义在类里,默认相当于加上了inline,编译器就可能会把它当做内联函数处理。加不加inline只是为了提醒编译器,到底是不是内联函数取决于编译器自己。

类的访问限定符

为了安全起见,类引入了三种访问限定符分别为public(公有),private(私密),protected(受保护的)

#include <iostream>using namespace std;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._year;成员变量_year是私密的不能在外部进行访问,只能在类中进行访问d1.Init(2004, 1, 01);d2.Init(2003, 1, 10);d1.Print();d2.Print();return 0;
}

public修饰的成员在类外可以被直接访问
protected和private修饰的成员在类外不能被直接访问
访问限定符的作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止,如果后面没有访问限定符,作用域就到 } 为止,即类结束。
class的默认访问权限为private,struct的默认访问权限为public(因为C++要兼容C)

类的实例化

#include <iostream>using namespace std;//类的实例化class Person
{
public:void MyName(){cout << _name << endl;}
public:char* _name;//类的成员变量要加上符号与普通变量加以区分char* _sex;int _age;
};int main()
{//Person.age = 20;未实例化不能使用类Person man;man.MyName();return 0;
}

其实就和之前的结构体一样你不能直接通过结构体类型去引用结构体的成员。
我们可以通过一个形象的例子来说明,这个类就像是一个房子的图纸,直接引用类的成员就相当于你要去这个图纸里主一样,你要先根据这个图纸把房子盖起来,然后才能去里面住。
这个图纸在还没有去建造的时候这个房子是不占空间的,你只有把房子盖起来了才会占据空间,同时你也可以根据这个图纸建造出很多个这样的房子,只不过这个房子所在的位置不同,类与建房子一样,可以实例出很多个类变量,且物理存储位置不同,在还没有对类进行实例化时,是不占空间的。

类对象的大小

类的大小是类中属性的大小还是方法的大小,还是属性和方法大小的总和呢?
先说结论类的大小只包括类中属性的大小,属性就是成员变量,不是方法。
我们还是拿房子举例,类中的成员变量就相当于是这个房子中的厨房,卧室,厕所等,这些属性当然每一个房子都会有,而成员方法就类似于篮球场,足球场等,可不可以放在家里呢?当然可以,但是未免也太占空间了,所以一般情况下小区的篮球场,足球场等是所有的居民共用的,所以这里的方法也是如此,它不存储在类中,而是放在一个公共区域内,供所有人使用。
类中成员变量的存储空间符合内存对齐。但是注意当这个类为空类时,就是没有成员变量的情况,默认占的内存空间为1,就相当于这个房子没有厨房,客厅,卧室等,但它仍然是一个房子是要占据空间的,是要让系统知道我这个房子是存在的。
此外结构体为什么要进行内存对齐?
假设你的系统在读取内存时一次读取八个字节,而一个值的存储恰好有一部分是存储在你所读的这八个字节中而另一部分是存储在下一次读取的八个字节中,那么对于这个数你就要读取两次,而如果是内存对齐呢这个数你只需要读一次就可以得到,具体内存对齐规则详见C语言三万字总结这篇文章。
那么又来了你也用我也用他也用这个健身房,怎么知道到底是谁再用呢?所以这就引出了另一个问题就是this指针。
this指针就像是在健身房人脸识别一样,每一个人都有一个脸,系统可以通过这张脸来识别你的身份。这张脸不需要你去设定,系统会自动帮你加上并识别。

#include <iostream>using namespace std;//this指针
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(2004, 1, 01);d2.Init(2003, 1, 10);d1.Print();d2.Print();return 0;
}

上述初始化函数Init()是调用的同一个函数,是怎么确定这个此时是给哪个类对象进行初始化的呢?你可能会说这不是写了d1.,d2.了吗,肯定是对它的成员进行初始化呀,我们要追根溯源找到它的本质原因,其实函数调用的括号里有一个默认的this指针。
C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量”的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。

this指针

this指针是你调用类成员方法时自动添加上的。
你不能主动地去给这个方法加上形参this,或指定这个对象的地址。
**this指针是存放在栈帧里面的,本质和形参一样没有区别,**只不过是隐式传过去的。
this指针不是存放在对象里面的是存放于栈中的


http://www.ppmy.cn/news/59488.html

相关文章

【剧前爆米花--爪哇岛寻宝】TCP/IP协议以及在网络传输过程中的封装与分用

作者&#xff1a;困了电视剧 专栏&#xff1a;《JavaEE初阶》 文章分布&#xff1a;这是一篇关于网络初识的文章&#xff0c;在这篇文章中讲解了TCP/IP协议的主要内容和砸在网络传输过程中的封装和分用&#xff0c;希望对你有所帮助&#xff01; 目录 TCP/IP五层模型 应用层…

五子棋游戏程序创作过程(C语言)

五子棋游戏程序创作过程&#xff08;C语言 &#xff09; 我是编程爱好者&#xff0c;对游戏程序编制很感兴趣。学习VB6语言时就编制过一些游戏程序&#xff0c;如独立钻石棋、伤脑筋十二块、连连看、扑克牌游戏等&#xff0c;都是windows标准图形界面的。感到很好玩&#xff0…

java获取文件名乱码

Java读linux系统文件文件名乱码的解决办法 1&#xff0c;问题描述 web应用想通过Java读取linux系统文件显示到web页面上&#xff0c;结果中文文件名出现乱码&#xff1f; 问题场景描述&#xff1a;当用户通过浏览器访问tomcat服务器&#xff0c;请求查看某一路径下文件列表信…

VSCode正确使用方式,你知道多少?

VSCode正确使用方式&#xff0c;你知道多少&#xff1f; 目录 VSCode正确使用方式&#xff0c;你知道多少&#xff1f;VSCode 是一款非常流行的代码编辑器&#xff0c;它支持丰富的插件扩展&#xff0c;可以帮助开发者提高开发效率。以下是一些常用的 VSCode 插件及其安装方法&…

day10 TCP是如何实现可靠传输的

TCP最主要的特点 1、TCP是面向连接的运输层协议。&#xff08; 每一条TCP连接只能有两个端点&#xff08;endpoint&#xff09;&#xff0c;每一条TCP连接只能是点对点的&#xff08;一对一&#xff09;&#xff09; 2、TCP提供可靠交付的服务。 3、TCP提供全双工通信。 4…

idea中maven的几个操作按钮:clean、validate、compile...

idea中Maven生命周期指令 clean命令 清除由项目编译创建的target validate命令 验证项目是否正确&#xff0c;并且所有必要的信息均可用 compile命令 编译项目的源代码 test命令 使用合适的单元测试框架来测试编译的源代码。 这些测试不应要求将代码打包或部署 verify命令 …

Java 中的线程是什么,如何创建和管理线程-中(十二)

书接上文 三、Java 线程的同步 Java 中的线程同步是通过 synchronized 关键字实现的。在多线程环境下&#xff0c;当多个线程同时访问共享资源时&#xff0c;如果不进行同步控制&#xff0c;就会出现数据不一致、死锁等问题。为了保证多个线程之间的安全访问&#xff0c;需要…

【Git 入门教程】第六节、Git高级操作

Git是一种非常强大的分布式版本控制系统&#xff0c;可以帮助开发者轻松地管理和协调代码库。在本文中&#xff0c;我们将介绍一些Git高级操作&#xff0c;包括如何管理Git仓库、标签、子模块和忽略文件。 一、管理Git仓库 Git提供了许多命令来管理本地Git仓库。以下是一些常用…