类和对象(上)

个人主页流年如梦

专栏《零基础轻松入门C语言》 《数据结构:从入门到掌握》 《C++编程研习录》

文章目录

前言

类和对象是C++面向对象编程的核心,也是从C语言过渡到C++的关键章节。本篇将详细讲解类的定义、访问限定、实例化、对象大小、this指针及封装特性,带你扎实掌握面向对象的基础语法与思想

一.类的定义

1.1什么是类

类是把++变量(属性)++ 和++函数(方法)++打包在一起,用来描述一类事物

成员变量 :描述对象的属性(如栈的数组、容量、栈顶)
成员函数 :操作这些属性的方法(InitPushPopTop等)

1.2类的定义格式

cpp 复制代码
class 类名
{
public:
    // 成员函数
private:
    // 成员变量
}; // 必须加分号!

1.3举例 --> 用类实现栈

cpp 复制代码
class Stack
{
public:
    //初始化
    void Init(int n = 4)
    {
        _a = (int*)malloc(sizeof(int) * n);
        _capacity = n;
        _top = 0;
    }
    //入栈
    void Push(int x)
    {
        //扩容逻辑...
        _a[_top++] = x;
    }
    //获取栈顶
    int Top()
    {
        return _a[_top - 1];
    }

private:
    int* _a;//成员变量加 _ 区分,这是行业习惯
    size_t _capacity;
    size_t _top;
};

1.4struct在C++中升级为类

  1. C++里struct可以定义函数
  2. 不再需要typedef
  3. 默认访问权限是publicclass默认是private
cpp 复制代码
struct Node
{
    void Init(int x)
    {
        _val = x;
        _next = nullptr;
    }
    int _val;
    Node* _next;
};

二.访问限定符

2.1三种访问权限

public :公有,类内外都能访问
private :私有,只有类内部能访问
protected :保护,和private类似(继承才体现区别)

2.2规则

  1. 访问限定符从当前位置开始生效,直到下一个限定符或类结束
  2. class默认private
  3. struct默认public

2.3为什么要用访问限定

因为这就是封装

  1. 把成员变量设为private禁止外部直接修改
  2. 把方法设为public提供安全接口
  3. 防止乱改数据,提高程序安全性

三.类域与声明定义分离

3.1什么是类域

每个类都是一个独立作用域(类域)

类外定义成员函数必须用 :: 作用域解析符

3.2类内声明与类外定义 --> 规范写法

cpp 复制代码
class Stack
{
public:
    void Init(int n = 4);//声明
private:
    int* _a;
    size_t _capacity;
    size_t _top;
};

//类外定义:必须写 Stack::
void Stack::Init(int n)
{
    _a = (int*)malloc(sizeof(int) * n);
    _capacity = n;
    _top = 0;
}

四.类的实例化

4.1什么是实例化

类创建对象的过程叫实例化

  1. 类是图纸,不占内存
  2. 对象是房子,占用真实内存
cpp 复制代码
int main()
{
    Date d1;//实例化对象 d1
    Date d2;//实例化对象 d2

    d1.Init(2024, 3, 31);
    d1.Print();
}

4.2注意事项❗

一个类可以实例化无数对象,彼此独立,互不影响

五.对象大小计算

5.1小结

对象只存成员变量,不存成员函数

  1. 成员变量:每个对象独有,占内存
  2. 成员函数:所有对象共享,存在代码段,不占对象空间

5.2对象大小遵循内存对齐规则

  1. 第一个成员从偏移0开始
  2. 其他成员对齐到:min (默认对齐数,成员大小) 的整数倍
  3. 总大小是最大对齐数的整数倍
  4. vs默认对齐数 --> 8

5.3空类 / 无成员变量类

大小为1字节,用来占位,表示对象存在

cpp 复制代码
class A {};
cout << sizeof(A) << endl; //结果输出1

六.this指针 --> C++类的灵魂

6.1为什么需要this指针

多个对象调用同一个成员函数,编译器不知道是哪个对象,所以就需要this指针区分

6.2什么是this指针

编译器会自动给每个成员函数 加一个隐藏指针Date* this

cpp 复制代码
//编译器看到的样子
void Init(Date* this, int year, int month, int day);

调用时:

cpp 复制代码
d1.Init(2024, 1, 1);
//编译器转为
Init(&d1, 2024, 1, 1);

6.3this指针的特性

  1. 隐含参数,我们不能写在形参里
  2. 可以在函数内部显式使用
  3. this指针是const指针,不能修改指向
  4. 存放在栈区(也可能寄存器)
cpp 复制代码
void Init(int year, int month, int day)
{
    this->_year = year;
    this->_month = month;
    this->_day = day;
}

6.4 经典面试题

题目一

cpp 复制代码
#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;
}

结果 --> 正常运行

🧐分析:函数不访问成员变量,不需要解引用空指针

题目二

cpp 复制代码
#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();//Print里访问了成员变量 _a

	return 0;
}

结果 --> 崩溃

🧐分析 :访问了this->_a,而thisnullptr

七.封装思想 --> C++三大特性之一

7.1什么是封装

  1. 将数据和操作数据的方法捆绑在一起
  2. 对外部隐藏实现细节
  3. 只开放安全接口
  4. 防止外部非法访问数据

7.2C语言 vs C++ --> 实现Stack(栈)对比

在C语言

  1. 结构体 + 外部函数
  2. 变量可以随便改,不安全
  3. 每次调用都要传指针

在C++

  1. 类把变量和函数包在一起
  2. 成员变量私有,不能乱改
  3. 自动传递this指针,代码更简洁

这样对比就体现了封装带来的规范与安全

🎯总结

  1. 类 = 成员变量 + 成员函数,class定义,末尾必须加分号
  2. 访问限定符public公有、private私有、protected保护
  3. struct在C++中是类 ,默认public
  4. 类域 :类外定义成员函数必须加类名 ::
  5. 实例化:类是图纸,对象是实体,才占内存
  6. 对象大小:只算成员变量,遵循内存对齐,空类 1 字节
  7. this指针:编译器自动加的隐藏指针,指向当前对象,存储在栈或寄存器
  8. 封装:数据安全、接口清晰、代码更易维护

⚠️易错点

  1. 类定义末尾忘记分号 ;
  2. 成员变量命名不加 _,和参数冲突
  3. 类外定义函数忘记写类域 ::
  4. 误以为对象大小包含成员函数
  5. 空类大小忘记是1字节
  6. this指针是const,不能修改指向
  7. 访问private成员导致编译报错
  8. nullptr调用访问成员的函数导致崩溃

👀 关注 我们一路同行,从入门到大师,慢慢沉淀、稳步成长
❤️ 点赞 鼓励原创,让优质内容被更多人看见
⭐ 收藏 收好核心知识点与实战技巧,需要时随时查阅
💬 评论 分享你的疑问或踩坑经历,一起交流避坑、共同进步

相关推荐
huipeng9262 小时前
基于SpringCloud的博客系统
java·运维·后端·spring·spring cloud·微服务
kyle~2 小时前
查找---插值查找(二分查找的改进版本)
开发语言·c++
高翔·权衡之境2 小时前
主题7:缓存与队列——速度不匹配的通用解
开发语言·人工智能·物联网·缓存·信息与通信·信号处理
@SmartSi2 小时前
AgentScope Java 入门:搭建第一个 ReAct 智能体
java·agentscope
小坏讲微服务2 小时前
SpringBoot整合SpringAI配置多平台API密钥
java·人工智能·spring boot·后端·flask·ai编程·claude code
:1212 小时前
java面试
java·开发语言·面试
ZC跨境爬虫2 小时前
跟着 MDN 学 HTML day_62:(HTML调试与常见错误修复指南)
java·前端·javascript·ui·html·媒体
霸道流氓气质2 小时前
Spring AI + Ollama 深度实战:从 RAG 问答到 Graph Agent 全流程指南
java·人工智能·spring
木井巳2 小时前
【递归算法】不同路径Ⅲ
java·算法·leetcode·深度优先