C++中的结构体与类

2023-05-16

C++中继承了C语言中的结构体,但同时也在C语言的基础上新增了一个类(class)的概念,类可以说是C语言中结构体的升级版,这里主要细讲C++中的类


1、C++结构体
2、C++类


1、c语言结构体:

在C语言中定义一个结构体变量时需要加上struct关键字的,但在C++中的结构体在定义变量时是可以不写struct关键字的,而且C++的结构体也有权限,权限默认为:公有(public),但结构体内不存在任何函数;测试代码:
#include <iostream>

struct AA
{
        int num;
};

int main()
{
        AA a;//可以不写struct关键字定义变量
        a.num = 5;
        std::cout << a.num << std::endl;
}

其他的C语言部分就不讲了,这里只讨论C++在C语言基础上做了什么改进
(注:C++中当结构体中没有成员时,结构体占一个字节)



2、C++中的类(class):

2.1、类与对象的关系
2.2、C++成员权限
2.3、类的定义
2.4、类的大小
2.5、类中隐含的指针
2.6、类中自带的函数
2.7、类继承
2.8、类成员方法默认参数
2.9、抽象类


类是C++中面向对象编程思想中比较重要的组成部分,与结构体一样类只是一个模板只有在创建对象时才会申请内存空间,类其实是把具有共同特性的数据或方法(面向对象编程中,一般把函数称为方法)都放在一起,用于创建对象时使用,下面分步骤来阐述C++的类:

(1)类与对象的关系

类是对象的创建模板
对象是类的实例化


(2)C++类成员权限

C++中为类成员设置访问权限,权限分为三种:

private(私有成员):只能类内进行访问
protected(保护成员):只能在类内或派生类中去访问
public(公有成员):可以类内或者类外进行访问在这里插入图片描述


(3)类的定义

定义时需要先写类的关键字class,后面跟着类名;花括号内是存放类成员的范围,花括号后需要与结构一样加个分号
示例代码:

class 类名
{
成员权限:
	类成员(变量,方法)
};

(4)类的大小

在C++中类的大小与成员数据有关,与成员方法无关
测试代码:

#include <iostream>

class AA
{
public:
       void print(){
			int num = 5;
			std::cout << num << std::endl;
		}
       
        int a;  
};

int main()
{
        AA a;
      	std::cout << sizeof(a) << std::endl;
    
        return 0;
}

运行结果:
在这里插入图片描述
由此可以证明C++中,类的大小只与成员数据有关,与成员方法无关;
(注:当类中没有成员数据时,或只有成员方法时;类占一个字节)



(5)类中隐含的this指针

其实我们创建的每一个C++类对象中都隐含有一个this指针,它存储着当前类对象的地址,因此我们可以通过this指针访问当前对象里的值
示例代码:

#include <iostream>

class AA
{
public:
        void print() {
                //当我们创建的类对象调用print函数时,打印当前类对象中a的值
                std::cout << this->a << std::endl;
        }
       
        int a;  
};

int main()
{
        AA a;
        a.a = 10; 
        a.print();
    
        AA b;
        b.a = 20; 
        b.print();
    
        return 0;
}


运行结果:
this指针



(6)类中自带的函数

构造函数:名字与类名一致,并且可以通过成员列表初始化参数;在创建对象时会默认生产且自动调用的函数,一般可用于初始化类成员等;因为默认的构造函数是没有任何操作的,此时需要我们去重写构造函数

class AA
{
public:
	//AA(){};  //普通构造函数
	AA(int num):number(num){} //构造函数 并使用成员初始化列表初始化成员数据            
	int number;
}:
/*成员初始化列表格式:在构造函数后加一个冒号然后把括号
里的数据初始化到成员中*/

拷贝构造函数:函数名与构造函数相似,但是需要传递一个类型与本类一致的一个变量的引用,在创建对象时会自动创建一个拷贝构造函数,拷贝构造函数相当于构造函数的重载函数,默认的拷贝构造函数在调用时其实只是把另一个已存在的类里的值都赋值到这个类中(这里的拷贝为浅拷贝),在类内存在堆空间问题时就需要我们重写拷贝构造函数实现深拷贝
class AA
{
public:
	AA(){};  //普通构造函数
	~AA(){}; //析构函数           
	int number;
}:

析构函数:析构函数的函数名与类名一致但要在前面加上 ~ 符,在创建的类对象会自动创建一个析构函数,且类对象被删除时会被自动调用,一般可用于类成员有申请堆空间内存时释放内存等,默认的析构函数是没有任何操作的,因此需要我们自己去重写析构函数
class AA
{
public:
	AA(){};  			//普通构造函数
	~AA(){}; 			//析构函数    
	AA(const AA &a){}; //拷贝构造函数       
	int number;
}:

注:
三个函数均无返回值,构造函数中支持成员参数初始化列表;且重写后的构造函数与析构函数,拷贝构造函数的权限必须为public


测试代码:

#include <iostream>

class AA
{
public:
        //构造函数
        AA(int num){
                std::cout << "调用了构造函数" << std::endl;
                this->a = new int(num); // 为a申请堆空间且初始化为10
        }
        
        //重写拷贝构造函数
        AA(const AA& b){	//这里的const可加可不加,默认加上最好
                std::cout << "调用了拷贝构造函数" << std::endl;
                this->a = new int(); // 为a申请堆空间且初始化为10
                *(this->a) = *(b.a);  //释放堆内存
        }

        //析构函数
        ~AA(){
                std::cout << "调用了析构函数" << std::endl;
                delete this->a;
        }
           void print(){
                std::cout << "a的值:" <<*(this->a) << std::endl;
                std::cout << "地址:" << this->a << std::endl;//打印一下地址
        }

private:
        int *a;
};

int main()
{
        AA a(10);
        AA b = a;

        b.print();
        a.print();

}
                                                                     
                                                                    

运行结果:
在这里插入图片描述
从运行结果中我们可以看到在创建对象a时,调用了构造函数,然后在创建对象b时调用的是拷贝构造函数,此时因为我们重写了拷贝构造函数(深拷贝),因此不会有任何问题,当我们把重写的拷贝构造函数注释掉后,我们会发现以下情况:

在这里插入图片描述

因为在拷贝构造函数中因为对象a中与对象b均带有一个指针,当我们使用默认的拷贝构造函数时,将会导致对象b里的成员变量指向的是对象a里申请的堆空间内存,它自己里面的成员变量是没有申请内存空间的;并且在对象a被删除后,析构时使得对象a中的堆空间内存被重复释放且b里面的成员变量也不能再去使用(会产生非法访问导致段错误),我们可以用一张图来解释深浅拷贝中的区别(图中的地址为假设的堆空间地址):
在这里插入图片描述



(7)类的is-a(public继承)关系与has-a(组合)关系

is-a关系是包含关系,has-a是拥有关系;如图:
在这里插入图片描述

①is-a(公有继承)关系我们举个简单的例子:就如我们把具有哺乳动物特效的动物称为哺乳动物,但哺乳动物是分为很多类的,有天上飞的,地上走的和水里游的;但是他们都具有哺乳动物的一种,因此我们可以说熊猫是哺乳动物的一种(is-a关系)
在C++中,is-a关系是通过基类与派生类(子类)间的继承实现的,派生类继承了基类后,派生类中就拥有了基类中的所有成员

其中继承的方式有三种:

private(私有继承):派生类private继承后,基类的成员在派生类中的权限均为private;派生类中想要使用只能通过调用方法来间接使用
protected(保护继承):派生类proteced继承后,public权限在派生类中变为protected权限,protected与private权限保持不变,派生类可直接使用
public(公有继承):派生类public继承基类后,在派生类中保持基类的中的成员权限在这里插入图片描述

注:在继承与组合关系中
(1)构造函数的调用顺序为:先基类再派生类
(2)析构函数的调用顺序为:先析构派生类再析构基类

测试代码:

#include <iostream>

class AA
{
public:
        AA(int num):number(num){}
protected:
        int number;  
};

//public继承
class BB :public AA
{
public:
        BB(int num):AA(num){}
        void print(){
                std::cout << "a = " << number <<std::endl;    
        }
};

int main()
{
        BB a(10);
        a.print();

        return 0;
}

运行结果:
类继承
此时我们通过创建BB类的对象时,因为类BB继承于AA的类,因此BB类中与AA类属于is-a关系,因为创建BB的类对象时,BB类包含了AA类因此会调用AA类中的构造函数,所以我们需要重写BB类中的构造函数并在成员初始化列表中给AA类的构造函数传递一个值过去,



②has-a(组合)关系就如:我们现在有一个盒子,然后盒子里面放了一个苹果;苹果与盒子两者是完全不相关的东西,我们只是把他们放到一起去使用而已;has-a关系就是两个不相干的类,但是我们可以把它们放到一起去使用
测试代码:

#include <iostream>

class Apple
{
public:
        Apple(int num):number(num){}
        int number;  
};

//public继承
class Box {
public:
        Box(int num):a(num){}   //通过成员初始化列表传参给Apple类的构造函数
        Apple a; //定义一个类对象
        void print(){
                std::cout << "apple = " << a.number <<std::endl;    
        }    
};

int main()
{
        Box a(10);
        a.print();

        return 0;
}

运行结果:
类组合
在组合中,我们在一个类中定义对象时可以直接定义,但是在需要传递参数时需要通过构造函数把需要传递的参数传递过去,因为对象在创建时就会默认先调用构造函数



(8)类成员方法的默认参数

类中的成员方法我们在编辑代码时是可以预先给予成员变量一个默认值的,当设置了默认参数后外部可不传递参数过来,当外部传递参数进来时就会覆盖掉默认参数的值;默认参数可写在声明或实现处,但一般写在声明处
测试代码:

#include <iostream>

using namespace std;

class Stu 
{
public:
     	Stu(int num=0,string name="lisi")
               :number(num),name(name)
       {

       }

       void print(){
                cout << "名字:" << this->name   << endl;
                cout << "学号:" << this->number << endl;
        }
    
private:
        int number;
        string name;  
};

int main()
{
       Stu lisi;//使用默认参数
       //Stu lisi(1,"lisi");//使用外部传的参数
       lisi.print();

       return 0;
}

运行结果:
默认参数

注意:在默认参数中只能从右到左的默认参数,即上面的代码,如果后面的name没有给"lisi"这个参数,前面的num就不能给默认值,否则会报错

(9)抽象类

我们把定义为虚函数,但是没有实现赋值为0 的虚函数称为纯虚函数,类中具有纯虚函数的类称为抽象类,抽象类是不能创建对象的,因为其成员方法还没有实现;抽象类只能作为基类,由派生类继承后重写该虚函数,派生类中若没有重写基类中的纯虚函数也将不能创建对象
格式:

class Box {
public:
		//纯虚函数
        virtual void print() = 0;    
};

本文仅个人理解,若有错误的地方麻烦提醒一下;非常感谢

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++中的结构体与类 的相关文章

  • 用matlab画简单曲线,并进行标注、图例、加网格,等操作

    用matlab画简单曲线 xff0c 并进行标注 图例 加网格 xff0c 等操作 工具 原料 matlab 软件 方法 步骤 本人采用的是r2012版本 xff0c 现简单的画两条曲线 xff0c 一条正弦 一条余弦 xff0c 线宽不同
  • Python程序的错误:变量未定义(NameError: name ‘mesage’ is not defined.)

    Python程序的错误种类 Python程序的错误分两种 一种是语法错误 xff08 syntax error xff09 这种错误是语句的书写不符合Python语言的语法规定 第二种是逻辑错误 xff08 logic error xff0
  • Ubuntu下PyCharm安装中文汉化包

    1 首先打开终端 2 进入临时文件夹 xff1a cd tmp 3 下载汉化包 xff1a git clone https github com ewen0930 PyCharm Chinese 若提示没有git 则根据提示安装即可 xff
  • 【matlab】矩形窗/三角窗/hanning窗/hamming窗/blackman窗的频率响应图

    File Matlab的窗函数 矩形窗 功能 xff1a 降低旁瓣水平 参数 xff1a N 61 51 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
  • eclipse无法导入项目由于“某些项目因位于工作空间目录中而被隐藏”

    从eclipse左侧的 资源管理器 中右击选择 删除项目 的方式删除项目后 xff0c 右击 导入项目 导入原来删除了的同名项目时 xff0c 会无法导入项目 xff0c 显示 某些项目因位于工作空间目录中而被隐藏 原因 xff1a ecl
  • 继承中父类与子类的构造与析构顺序

    父类与子类的构造与析构顺序 继承中的顺序如下 xff1a 先构造父类 xff0c 在构造子类 析构顺序与构造顺序相反 span class token macro property span class token directive ke
  • 基于ROS+CANopen的SocketCAN驱动在Ubuntu下的应用说明

    基于ROS 43 CANopen的SocketCAN驱动在Ubuntu20 04 18 04上的应用说明 摘要 Abstract keywords 在Ubuntu 20 04或者18 04里 xff0c 运用ROS下的CANopen消息机制
  • HDFS详解一

    前言 xff1a 一 HDFS的一些基本概念 xff1a 数据块 xff08 block xff09 xff1a 大文件会被分割成多个block进行存储 xff0c block大小默认为128MB 每一个block会在多个datanode上
  • potplayer播放器没有声音的解决方案

    potplayer播放器没有声音的解决方案 最近突然发现电脑上的potplayer播放视频文件的时候只有图像没有声音了 xff0c 卸载后重装依旧如此 经一番摸索 xff0c 解决方法如下 1 在播放界面按一下 m 键 xff0c 可以开启
  • 解决Mysql安装之后没有my.ini配置文件问题

    详记MySql问题大全集 三 安装之后没有my ini配置文件怎么办 系列目录 一 安装MySql 二 安装并破解Navicat 三 没有my in配置文件怎么办 四 设置MySql的大小写敏感 五 重置MySql登陆密码 之前说过 xff
  • 一个简单的环形进度条组件 vue-circleprogressbar

    vue circleprogressbar 一个简单的环形进度条组件 最近在开发可视化大屏项目中经常会用到环形进度条 但是常用的echarts组件对环形进度条的支持不太好 写起来比较麻烦 就想着自己写一个VUE的环形组件 满足自己日常开发需
  • Hbuilder如何创建并运行Vue项目

    在Hbuilder中开发Vue项目是非常快捷的 xff0c 下面小编给大家分享一下如何在Hbuilder中创建并运行Vue项目 方法 步骤 1 首先打开Hbuilder创建一个新项目 xff0c 如下图所示 2 Hbuilder如何创建并运
  • 教大家防止Jar包被反编译

    xff08 待验证 xff09 方法就是 xff0c 向Jar注入无效代码 xff08 不合法的 xff0c 或者根本不是代码的字符串 xff09 那么无效的代码又怎么能正确运行呢 xff1f 答案就是 xff0c 你要保证你的代码永远不会
  • 推荐3个小程序开源组件库——Vant、iView、ColorUI

    推荐3个小程序开源组件库 在进行小程序开发时 xff0c 经常会遇到编写组件方面的阻碍 xff0c 这让我们花费大量的时间在页面以及 CSS 样式编写上 因此可以使用开源组件库 xff0c 有些复杂的组件可以直接拿来使用 xff0c 节省开
  • 试图加载格式不正确的程序。 (异常来自 HRESULT:0x8007000B)

    两种原因 第一种为程序的运行以平台系统位数不匹配 第二种则是该死的VS整出来的 一般在下面三种情景下会发生 1 64位系统上C 调用32位的C 43 43 dll 2 64位系统上IIS发布含有32位的 dll应用程序时 3 64位系统上编
  • 怎么进bios设置硬盘启动顺序|电脑bios硬盘启动设置方法

    怎么在BIOS里设置硬盘启动 xff1f 电脑在启动时会从硬盘寻找引导文件 xff0c 从而启动系统 xff0c 如果硬盘不是第一启动项 xff0c 或者有两个硬盘 xff0c 就会导致系统无法启动 xff0c 这时候就需要进BIOS设置硬
  • Windows计划任务执行时不显示窗口的问题

    最近开发了工具 xff0c 带界面的 xff0c 需要定时执行的 xff0c 为了方便直接用Windows计划任务做定时了 跑了一段时间发现 xff0c 进程中也有 xff0c 就是看不到程序的界面 xff0c 进程的执行貌似也阻塞了 从网
  • JAVA的@EXCEL导出导入常用注解汇总

    在实际开发中经常需要使用导入导出功能来加快数据的操作 在项目中可以使用注解来完成此项功能 在需要被导入导出的实体类属性添加 64 Excel注解 参数类型默认值描述sortintInteger MAX VALUE值越小越靠前readConv
  • MySQL中order by排序将NULL排在最前或最后面

    NULL的意思表示什么都不是 xff0c 或者理解成 未知 也可以 xff0c 它与任何值比较的结果都是false 注意 xff1a 默认情况下 xff0c MySQL会认为NULL值比其他类型的数据小 xff0c 也就是说 xff1a 在

随机推荐

  • C# 如何获取本机IP

    百度搜索的方案 如果你去百度C 如何获取本机IP xff0c 那么大概率的你会得到以下的几段代码 xff0c 第一种就是这样 xff1a string name 61 Dns GetHostName IPAddress ipadrlist
  • winform DevExpress contextMenuStrip右键事件

    span class token keyword private span span class token return type class name span class token keyword void span span sp
  • Linux TCP连接数限制配置

    在进行接口测试时 xff0c 在用户数超过400后 xff0c 就会出现socket connection reset xff0c 明显就是系统无法创建连接 xff0c 查看此时系统建立的TCP连接 xff0c netstat ant gr
  • 摘要认证及实现HTTP digest authentication

    最近工作需要做了摘要认证 xff08 digest authentication xff09 xff0c 下面就工作中遇到的问题及过程做一个总结 第一次客户端请求 GET POST 服务器产生一个随机数nonce xff0c 服务器将这个随
  • HTTPURL Connection及session保存问题

    HTTPURL Connection及session保存问题 HTTPURL Connection是一种多用途 轻量极的HTTP客户端 xff0c 使用它来进行HTTP操作可以适用于大多数的应用程序 虽然HttpURLConnection的
  • SpringBoot 集成redis-jedis

    SpringBoot 集成redis jedis 配置application properties中的redis Redis配置 Redis数据库索引 xff08 默认为0 xff09 spring redis database 61 0
  • Python爬虫常用之登录(三) 使用http请求登录

    前面说了使用浏览器登录较为简单 不需要过多分析 而使用请求登录恰恰就是以分析为主 开发一个请求登录程序的流程 分析请求 gt 模拟请求 gt 测试登录 gt 调整参数 gt 测试登录 gt 登录成功 一 分析网页 从网页着手 打开博客园的登
  • memmove的算法思想

    1 memmove的用法 C 库函数 void memmove void str1 const void str2 size t n 从 str2 复制 n 个字符到str1 如果目标区域和源区域有重叠的话 memmove 能够保证源串在被
  • 菜菜之路-C语言求阶乘和

    提示 xff1a 文章写完后 xff0c 目录可以自动生成 xff0c 如何生成可参考右边的帮助文档 文章目录 前言一 阶乘是什么 xff1f 二 思想 1 思路12 思路2总结 前言 C语言其实要学好并不简单碰到一道题我们有时根本无从下手
  • 题目:将一个正整数分解质因数。例如:输入90,打印出90=2 * 3 * 3 * 5

    思路1 xff1a 首先先提一个这样的思路 假如这个数是90 xff0c 我们让它被2到90之间的数进行整除 xff0c 如90 2 61 45 0 余数 xff0c 90 3 61 30 我们获取这样的除数 但是有问题 xff0c 90每
  • C语言--求比赛名次问题

    题目内容 xff1a 5位运动员参加了10米台跳水比赛 xff0c 有人让他们预测比赛结果 xff1a A选手说 B第二 xff0c 我第三 B选手说 我第二 xff0c E第四 C选手说 我第一 xff0c D第二 D选手说 C最后 xf
  • 编写程序,输入一个较小的实数deta,利用e=1+1/1(嘿哈)+1/2(嘿哈)+1/3(嘿哈)+⋯+1/n(嘿哈)计算e的近似值,直到最后一项的绝对值小于deta时为止,输出此时e的近似值。

    碰到了一种避开惯性思维的写法想分享出来 由于标题不能打叹号 你品一下哈 include lt stdio h gt include lt math h gt int main int n 61 1 double e 61 1 0 term
  • Linux主板支持多机系统的Mark/Space校验

    Linux主板支持多机系统的Mark Space校验 关键词 xff1a Linux 主板摘要 xff1a 英创Linux主板可以通过RS485总线挂载多个单片机组成多机系统 xff0c 当从机设备比较多 传输数据比较频繁的时候 xff0c
  • 库函数memcpy的实现

    1 先看一下memcpy的声明 从str2所指向的内容的n个字节 复制到str1所指向的内容中 注意这里是n个字节 后面实现该库函数时我会详细解释 size t你们可以查一下它的定义 代表着无符号整型 2 好 来看看我们如何实现它 void
  • linux 抓包tcp

    tcpdump是linux下的网络数据包截获分析工具 在linux的日常网络管理中 xff0c tcpdump的使用频率很高 xff0c 熟练掌握对提高工作效率很有帮助 支持针对网络层 协议 主机 网络或端口的过滤 并提供and or no
  • STM32串口中断接收一帧数据

    STM32串口中断接收一帧数据 IDLE即串口空闲中断 xff0c 串口收到一帧数据后 xff0c 发生的中断 比如说给单片机一次发来1个字节 xff0c 或者一次发来8个字节 xff0c 这些一次发来的数据 xff0c 就称为一帧数据 x
  • shell中各种括号的作用()、(())、[]、[[]]、{}

    一 小括号 xff0c 圆括号 xff08 xff09 1 单小括号 命令组 括号中的命令将会新开一个子shell顺序执行 xff0c 所以括号中的变量不能够被脚本余下的部分使用 括号中多个命令之间用分号隔开 xff0c 最后一个命令可以没
  • 双极性(相)四线步进电机TC1508S(双通道直流马达驱动器)

    实验现象 xff1a 下载程序后 xff0c 步进电机旋转 接线说明 xff1a 具体接线图可见开发攻略对应实验的 实验现象 章节 1 xff0c 单片机 gt 四线双极性步进电机模块 P10 gt IA P11 gt IB P12 gt
  • c语言实现广播(udp协议)

    广播 xff1a 顾名思义可以把自己的数据发送给在特定范围内的所有人 xff1b 我们网络编程中的广播一般是通过特定的广播地址把自己的数据发送给局域网内当前在线的客户端 我们可以使用命令查看我们Linux下当前的广播地址 xff1a ifc
  • C++中的结构体与类

    C 43 43 中继承了C语言中的结构体 xff0c 但同时也在C语言的基础上新增了一个类 class 的概念 xff0c 类可以说是C语言中结构体的升级版 这里主要细讲C 43 43 中的类 1 C 43 43 结构体 2 C 43 43