当前位置: 首页 > news >正文

C++类和对象(1) - 详解

C++类和对象(1)

  • 1.类的定义
  • 2.访问限定符
  • 3.类域
  • 4.对象的大小
  • 5.this指针

如果我想把人这个对象封装起来。
经过C语言的学习,我们可以使用结构体,里面可以定义人的种种数据。
但是如果这个人的一些数据是涉及隐私的,不想让用户知道的,该怎么办呢?
这就是今天我们学习的类与结构体的核心区别。

1.类的定义

如果是结构体,我们这样定义。

struct Date
{
int _year;
int _month;
int _day;
};

如果是类,我们这样定义。

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;//成员变量
};

class为类的关键字,后面是类名,{}中是类的主体。
类体中内容称为类的成员:类中的变量称为类的属性或成员变量,类中的函数称为类的方法或成员函数。
因为有了在成员变量前面加了private:所以我们在除了类中的所有地方都不能直接访问这个类的成员函数。
成员函数默认为inline

2.访问限定符

分为三个:public,private,protected
在现阶段的学习中我们可以暂且认为private与protected作用一样。
class定义成员时没有被访问限定符修饰时默认为private

3.类域

类定义出了一个新的作用域。在类外定义成员时,需要加上::作用域操作符指明成员属于哪个类域

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

4.对象的大小

在C语言学习时,我们学习了如何判断结构体的大小与内存对齐规则。
C++也规定实例化的对象要符合内存对齐的规则。

  • 第一个成员在于结构体偏移量为0的地址处
  • 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处
  • 对齐数 =(编译器默认的一个对齐数)与(该成员大小)的较小值
  • vs中默认对齐数是8
  • 最大对齐数 =(所有变量类型最大者)与(默认对齐数)取较小
  • 结构体总大小为最大对齐数的整数倍

注意
对象中不存储成员函数,因为函数被编译后是一段指令,它们无法存储在对象中。这些指令存储在单独的区域(代码段)。

#include<iostream>using namespace std;// 计算⼀下A/B/C实例化的对象是多⼤? class A{public:void Print(){cout << _ch << endl;}private:char _ch;int _i;};class B{public:void Print(){//...}};class C{};int main(){A a;B b;C c;cout << sizeof(a) << endl;cout << sizeof(b) << endl;cout << sizeof(c) << endl;return 0;}

在这里插入图片描述

为什么b和c的大小是1呢?完全是因为要代表这个对象存在,不得不分配一个字节来说明其存在。

5.this指针

以上面的Date类为例,当我们创建了两个对象的d1.d2并调用成员函数时,该函数是如何知道应该访问d1还是d2呢?
编译器编译后,类的成员函数默认都会在形参第⼀个位置,增加⼀个当前类类型的指针,叫做this指针。比如Date类的Init的真实原型:
void Init ( Date* const this, int year, int month, int day )

  • 类的成员函数中访问成员变量,本质都是通过this指针访问的,如Init函数中给_year赋值, this->_year = year;
  • C++规定不能在实参和形参的位置显⽰的写this指针(编译时编译器会处理),但是可以在函数体内显示使用this指针。

所以其实void Init( int year, int month, int day)就等价于
void Init(Date* const this, int year, int month, int day)

接下来是两道经典例题

#include<iostream>using namespace std;class A{public:void Print(){cout << "A::Print()" << endl;}private:int _a;};int main(){A* p = nullptr;p->Print();return 0;}

A.编译报错 B.运行崩溃 C.正常运行
注意:
当指针指向的内容是对象时,用它调用类中变量和函数的本质(类似p->Print())是将自己传给this指针。并非真正的解引用。
当我们调试转到反汇编时:
在这里插入图片描述
所以p->Print();实际上并没有发生解引用这一步,自然不会报错。
所以选C

#include<iostream>using namespace std;class A{public:void Print(){cout << "A::Print()" << endl;cout<<_a<<endl;}private:int _a;};int main(){A* p =nullptr;p->Print();return 0;}

A.编译报错 B.运行崩溃 C.正常运行
在这里插入图片描述
在Print函数中,_a就是this->_a,而p指针是空指针,所以this也是空指针,所以会运行错误。

如有错误,欢迎打在评论区。
主页还有更多优质内容OvO

http://www.jsqmd.com/news/24933/

相关文章:

  • 人工智能之编程基础 Python 入门:第二章 Python 的编辑器 VS Code
  • 2019 福建省队集训录
  • AIX multibos bootlist
  • 记录一次nginx能通但是请求一直不了的问题
  • 【嵌入式】PWM DAC的滤波器设计
  • 被称作遗憾之物 爬满了脊骨 又把控了痛楚 被称作无用之物 修筑了唯一的通路
  • neovim在windwos11下snack.nvim的问题
  • 完整教程:Java 集合 “List + Set”面试清单(含超通俗生活案例与深度理解)
  • 禁用 IPython 历史记录 history.sqlite
  • Luogu P7914 [CSP-S 2021] 括号序列 题解 [ 蓝 ] [ 区间 DP ] [ 前缀和优化 ] [ 调试技巧 ]
  • 扩展BaseMapper类 - 详解
  • 《程序员修炼之道:从小工到专家》前五分之二观后感
  • 矩阵快速幂章节笔记(这里主要介绍的是我的错题)
  • 实验二 现代C++编程初体验
  • P5322 [BJOI2019] 排兵布阵
  • 题解:P9292 [ROI 2018] Robomarathon
  • [题解]P5322 [BJOI2019] 排兵布阵
  • 考前打印
  • 申威服务器安装Nacos 2.0.3 RPM包详细步骤(Kylin V10 sw_64架构)​附安装包
  • ZKY精选冲刺省选国赛仿真训练题
  • MySQL 查询与更新语句执行过程深度解析:从原理到实践​ - 指南
  • ZKY精选冲刺省选国赛技巧训练题
  • 逆向基础--编码(001)
  • 20251027 - 倍增 ST表
  • 周康阳精选冲刺省选国赛思维训练题
  • Luogu P7913 [CSP-S 2021] 廊桥分配 题解 [ 绿 ] [ 贪心 ] [ 前缀和 ] [ STL ]
  • 10-27 CSP 赛前比赛记录
  • P3939 数颜色
  • 完整教程:Docker 搭建 Nginx 并启用 HTTPS 具体部署流程
  • AI开发微信小程序-有感