首页 > 编程语言 >C++:类的定义、实例化

C++:类的定义、实例化

时间:2024-08-31 13:23:16浏览次数:6  
标签:定义 int 成员 C++ 对象 实例 对齐 struct

目录

一、类的定义

1.1 类的定义格式

1.2 访问限定符

1.3 类域

二、实例化

2.1 实例化概念

2.2 对象大小


一、类的定义

1.1 类的定义格式

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

• 为了区分成员变量,一般习惯上成员变量会加⼀个特殊标识,如成员变量前面或者后面加_ 或者  m 开头,注意C++中这个并不是强制的,只是⼀些惯例。

• C++中struct也可以定义类,C++兼容C中struct的用法,同时struct升级成了类,明显的变化是 struct中可以定义函数,⼀般情况下我们还是推荐用class定义类。

• 定义在类面的成员函数默认为inline。

class Date
{
public:
 void Init(int year, int month, int day)
 {
 _year = year;
 _month = month;
 _day = day;
 }
private:
 // 为了区分成员变量,⼀般习惯上成员变量 
 // 会加⼀个特殊标识,如_ 或者 m开头 
 int _year; // year_ m_year
 int _month;
 int _day;
};
int main()
{
 Date d;
 d.Init(2024, 3, 31);
 return 0;
}

     值得注意一点的是在C++中struct升级成了类,类里面可以定义函数,struct名称就可以代表类型,不再需要typedef,但是可以写,C++也兼容C中的struct写法。

// C++兼容C中struct的⽤法 
typedef struct ListNodeC
{
 struct ListNodeC* next;
 int val;
}LTNode;
// 不再需要typedef,ListNodeCPP就可以代表类型 
struct ListNodeCPP
{
 void Init(int x)
 {
 next = nullptr;
 val = x;
 }
 ListNodeCPP* next;
 int val;
};

1.2 访问限定符

• C++⼀种实现封装的方式,用类将对象的属性与方法结合在⼀块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用。

• public修饰的成员在类外可以直接被访问;protected和private修饰的成员在类外不能直接被访 问,protected和private是一样的,以后继承章节才能体现出他们的区别。

• 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止,如果后面没有 访问限定符,作用域就到 } 即类结束。

• class定义成员没有被访问限定符修饰时默认为private,struct默认为public。

• ⼀般成员变量都会被限制为private/protected,需要给别人使用的成员函数会放为public。 

 

1.3 类域

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

• 类域影响的是编译的查找规则,下面程序中Init如果不指定类域Stack,那么编译器就把Init当成全局函数,那么编译时,找不到array等成员的声明/定义在哪里,就会报错。指定类域Stack,就是知道Init是成员函数,当前域找不到的array等成员,就会到类域中去查找。

#include<iostream>
using namespace std;
class Stack
{
public:
 // 成员函数 
 void Init(int n = 4);
private:
 // 成员变量 
 int* array;
 size_t capacity;
 size_t top;
};
// 声明和定义分离,需要指定类域 
void Stack::Init(int n)
{
 array = (int*)malloc(sizeof(int) * n);
 if (nullptr == array)
 {
 perror("malloc申请空间失败");
 return;
 }
 capacity = n;
 top = 0;
}
int main()
{
 Stack st;
 st.Init();
 return 0;
}

二、实例化

2.1 实例化概念

• 用类类型在物理内存中创建对象的过程,称为类实例化出对象。

• 类是对象进行⼀种抽象描述,是⼀个模型⼀样的东西,限定了类有哪些成员变量,这些成员变量只是声明,没有分配空间,用类实例化出对象时,才会分配空间。

• ⼀个类可以实例化出多个对象,实例化出的对象占用实际的物理空间,存储类成员变量。打个比方:类实例化出对象就像现实中使用建筑设计图建造出房子,类就像是设计图,设计图规划了有多 少个房间,房间大小功能等,但是并没有实体的建筑存在,也不能住人,用设计图修建出房子,房 子才能住人,同样类就像设计图一样,不能存储数据,实例化出的对象分配物理内存存储数据。

 

#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 
 Date d1;
 Date d2;
 d1.Init(2024, 3, 31);
 d1.Print();
 d2.Init(2024, 7, 5);
 d2.Print();
 return 0;
}

2.2 对象大小

    分析⼀下类对象中哪些成员呢?类实例化出的每个对象,都有独立的数据空间,所以对象中肯定包含成员变量,那么成员函数是否包含呢?首先函数被编译后是⼀段指令,对象中没办法存储,这些指令存储在一个单独的区域(代码段),那么对象中非要存储的话,只能是成员函数的指针,再分析一下,对象中是否有存储指针的必要呢,Date实例化d1和d2两个对象,d1和d2都有各自独立的成员变量 _year/_month/_day存储各自的数据,但是d1和d2的成员函数Init/Print指针却是⼀样的,存储在对象中就浪费了,如果用Date实例化100个对象,那么成员函数指针就重复存储100次,太浪费了。 

 

    上面我们分析了对象中只存储成员变量,C++规定类实例化的对象也要符合内存对齐的规则。

内存对齐规则

• 第一个成员在与结构体偏移量为0的地址处。

• 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。

• 对齐数 = 编译器默认的⼀个对齐数与该成员大小的较小值。

• VS中默认的对齐数为8。

• 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。

• 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

class B
{
public:
 void Print()
 {
 //...
 }
};
class C
{};

     上面的程代码成员变量的B和C类对象的大小是1为什么没有成员变量还要给1个 字节呢?因为如果一个字节都不给,怎么表示对象存在过呢!所以这里给1字节,纯粹是为了占位标识 对象存在。


    本篇关于类的定义和实例化的内容就到这里了,希望对各位有帮助,如果有错误欢迎指出。

标签:定义,int,成员,C++,对象,实例,对齐,struct
From: https://blog.csdn.net/2401_86551514/article/details/141727477

相关文章

  • 高并发系统-使用自定义日志埋点快速排查问题
    背景在高并发的系统中,通常不会打印除参数校验失败或捕获异常之外的日志,防止对接口的性能产生影响。那对于请求不符合预期的情况,我们如何快速找到是哪块逻辑影响的至关重要。Pfinder提供的链路监控,更多的是性能层面的监控,无法满足我们上述的诉求。下面我将通过自定义通用上下文,添加......
  • C语言(vs2022、Vc++6.0、DevC++)连接MySql
    本文c++(OraOla编写)与Java(Wideskyzz编写)由于csdn的排版太垃圾了,所以可以直接看资料上传资料也麻烦,所以可直接访问我的giteeC语言连接MySql:C语言(vs2022、Vc++6.0、DevC++)连接MySqlhttps://gitee.com/gyhjim/c-language-connection---my-sql一定要自己实践当你发现与我的......
  • 第七章 项目布局实现(7.4.7)——自定义主题
    7.4.7自定义主题==强烈建议:==在模板中不要配置与颜色有关的样式,否则自定义主题不生效很难排错。明亮模式新建src/styles/element/light.scss//onlyscssvariables$--colors:('primary':('base':green,),);@forward'element-plus/theme-ch......
  • 第七章 项目布局实现(7.4.5)——ElementPlus 自定义命名空间
    7.4.5ElementPlus自定义命名空间参考:https://cn.element-plus.org/zh-CN/guide/namespace.htmlElementPlus提供的默认命名空间为el。在特殊情况下,我们需要自定义命名空间。我们使用sass书写样式,必须同时设置ElConfigProvider和scss$namespace。设置ElC......
  • (2024最新毕设合集)基于SpringBoot的校园设备维修管理系统-16364|可做计算机毕业设计JAV
    基于Springboot的校园设备维修管理系统的设计与实现摘 要基于Springboot的校园设备维修管理系统的设计与实现是一个结合了网络技术和信息管理的项目。该系统能满足校园报修管理的实际需求,通过网络进行信息管理,使得设备维修更加及时有效。本设计主要实现集人性化、高效率、......
  • Qt/C++地址转坐标/坐标转地址/逆地址解析/支持百度高德腾讯和天地图
    一、前言说明地址和经纬度坐标转换的功能必须在线使用,一般用在导航需求上,比如用户输入起点地址和终点地址,查询路线后,显示对应的路线,而实际上各大地图厂家默认支持的是给定经纬度坐标来查询(百度地图支持传入地址),但是你让用户输入经纬度坐标是不可能的,他肯定不可能知道怎么去拿到这......
  • .NET|--WPF|--笔记合集|--依赖项属性|--1.定义依赖项属性
    前言一般情况下,我们是不用定义依赖项属性的,更多的是直接使用即可.那么何时需要我们定义依赖项属性呢?1.设计自定义的WPF元素;2.为原本不支持数据绑定,动画等WPF功能的代码中,需要添加数据绑定,动画等WPF功能时.定义依赖项属性一般的类型来说,如果想要使用的......
  • C++学习,指针空指针
    C++空指针,一个在几个标准库中定义的值为零的常量。如果没有分配的地址,将指针NULL分配给指针变量,指定为NULL的指针称为null指针。大多数操作系统上,不允许访问地址0的内存,因为该内存是由操作系统保留的。NULL指针是一个常量,其值为零,在几个标准库中定义,包括iostream。 示例:#i......
  • 【每日一题】【想通后的诈骗题】Wakey Wakey 牛客挑战赛76 A题 C++
    牛客挑战赛76A题WakeyWakey题目背景牛客挑战赛76题目描述样例#1样例输入#12232100001000002333样例输出#112014备注1≤T......
  • 【C++】单元测试覆盖率工具lcov的使用
    本文首发于❄️慕雪的寒舍本文讲述了如何在C++代码中使用单元测试覆盖率工具lcov,以及gcov命令的使用。版本是lcov2.0和gcov11.4.0。写在前面:lcov是我在实习期间初次接触到的工具,当时在配置的时候就遇到了大量中文互联网没有任何记录的问题。绝大部分博客对lcov工具的......