面向对象深度理解

一、面向对象的本质

面向对象 = 数据 + 操作数据的方法 捆绑在一起

目的:高内聚、低耦合、易复用、易维护

三大特性(深度版):

  1. 封装:把数据藏起来,只暴露接口(安全、可控)
  2. 继承:复用代码,扩展功能(代码复用)
  3. 多态:父类指针指向子类对象,调用不同实现(灵活扩展)

二、封装深度理解

1. 封装不是私有变量那么简单

它的真正意义:

  • 隐藏实现:外面不知道内部怎么存、怎么算
  • 控制访问:只能通过我允许的方式修改数据
  • 降低耦合:我内部改代码,外面不用动
cpp 复制代码
class User {
private:
    int age; // 私有数据,外部不能直接碰
public:
    void setAge(int a) { // 我控制怎么赋值
        if (a < 0 || a > 150) return;
        age = a;
    }
};

2. 类的内存本质

对象内存 = 成员变量总和

成员函数不占对象内存! 所有对象共享一套代码。

cpp 复制代码
class A {
    int a;
    void f() {}
};
// sizeof(A) = 4(只存 int)

三、继承深度理解(重点+坑点)

1. 继承本质

子类对象 = 父类部分 + 子类新增部分

父类在前,子类在后。

cpp 复制代码
class Base { int a; };
class Derive : public Base { int b; };
// 内存布局:[ a | b ]

2. 三种继承权限(必须懂)

  • public:父类public/protected保持不变
  • protected:父类public变protected
  • private:父类所有都变private

3. 构造/析构调用顺序(必考)

构造:父类 → 成员对象 → 子类

析构:子类 → 成员对象 → 父类

4. 父类析构函数必须是 virtual!

cpp 复制代码
~Base() = default; // ❌ 内存泄漏
virtual ~Base() = default; // ✅ 正确

原因:

父类指针删除子类对象时,只有虚析构才能调用到子类析构

5. 菱形继承 + 虚继承(难点)

复制代码
Student  Teacher
   \      /
    People

问题:子类有两份 People

解决:虚继承

cpp 复制代码
class Student : virtual public People {}

本质:加一个指针,共享父类数据,消除冗余。


四、多态深度理解(最核心、面试必问)

1. 多态的本质

同一个接口,不同实现

cpp 复制代码
Base* p = new Son();
p->show(); // 调用 Son 的 show ✅ 多态

2. 多态的底层原理(超级重点)

虚函数 + 虚表 + 虚指针

  • 有虚函数的类,编译器生成虚表(vtable)
  • 对象里多一个虚指针(vptr)
  • 调用时通过虚指针 → 虚表 → 找到函数地址

内存布局(有虚函数)

复制代码
对象:
[vptr][成员变量...]

虚表:
函数1地址
函数2地址
...

多态调用过程

复制代码
p->func()
→ 取对象前4/8字节 vptr
→ 找到虚表
→ 查表得到函数地址
→ 调用

3. 多态成立的三个条件

  1. 有虚函数
  2. 子类重写(override)虚函数
  3. 父类指针/引用指向子类对象

4. 纯虚函数 & 抽象类

cpp 复制代码
virtual void func() = 0;
  • 没有实现
  • 类变成抽象类
  • 不能创建对象
  • 强制子类必须实现

五、四大函数深度理解(OOP灵魂)

任何一个类,自动生成4个函数:

  1. 构造函数
  2. 析构函数
  3. 拷贝构造
  4. 拷贝赋值

1. 浅拷贝 vs 深拷贝(超级坑)

  • 浅拷贝:只拷贝指针(两个对象共用一块内存)
  • 深拷贝:重新开辟空间,拷贝数据(安全)

有指针必须写深拷贝

cpp 复制代码
A(const A& other) {
    data = new int(*other.data); // 深拷贝 ✅
}

2. 移动语义(C++11 现代OOP)

cpp 复制代码
A(A&& other) { // 移动构造
    data = other.data;
    other.data = nullptr;
}

偷别人的资源,不拷贝,超快!


六、重载 / 重写 / 隐藏(彻底分清)

1. 重载(overload)

同一个类,同名函数,参数不同

cpp 复制代码
void f(int);
void f(double);

2. 重写(override)

子类重写父类虚函数

  • 函数名/参数/返回值完全一样
  • 必须有 virtual

3. 隐藏(hide)

子类函数与父类同名,没有 virtual

  • 子类隐藏父类函数
  • 不属于多态

七、面向对象设计原则(企业级)

  1. 单一职责:一个类只干一件事
  2. 开闭原则:对扩展开放,对修改关闭
  3. 里氏替换:子类可以替换父类
  4. 接口隔离:接口小而专
  5. 依赖倒置:依赖抽象,不依赖具体

八、面试必问 12 题(答案直接背)

  1. 多态底层原理?
    虚指针 + 虚表
  2. 父类析构为什么要 virtual?
    防止内存泄漏,保证子类析构被调用
  3. 浅拷贝和深拷贝区别?
    浅拷贝共用内存,深拷贝独立内存
  4. 什么是抽象类?
    有纯虚函数,不能实例化
  5. 类的大小由什么决定?
    成员变量,不含成员函数
  6. 菱形继承问题?
    数据冗余,虚继承解决
  7. 构造析构顺序?
    父类→成员→子类;逆序析构
  8. 重载、重写、隐藏区别?
    参数不同/虚函数重写/同名无虚函数
  9. 空类大小?
    1字节
  10. 成员函数存在哪里?
    代码段,所有对象共享
  11. this指针是什么?
    指向当前对象的指针
  12. 什么时候用多态?
    统一接口,不同行为

九、终极总结(背会这一段)

  • 封装:数据私有,接口公开,安全可控
  • 继承:复用代码,扩展功能,顺序构造
  • 多态:虚表+虚指针,父类指针调用子类实现
  • 深拷贝:有指针必须写
  • 虚析构:继承必须加
  • 面向对象 = 数据 + 行为 + 可扩展
相关推荐
爱喝水的鱼丶1 小时前
SAP-ABAP:SAP 简单报表输出开发系列(共6篇) 第四篇:SAP 报表异常处理机制:数据校验与消息提示规范落地
开发语言·数据库·学习·算法·sap·abap
影寂ldy1 小时前
C# const 常量 / readonly 只读 / static readonly
java·开发语言·c#
摇滚侠1 小时前
Maven 入门+高深 体系外 jar 包导入 172
java·maven·jar
做个文艺程序员1 小时前
第02篇:K8s 存储与配置管理:ConfigMap、Secret、PV/PVC 实战——Java SaaS 多租户配置最佳实践
java·容器·kubernetes
爱吃牛肉的大老虎1 小时前
Spring中用到的设计模式
java·spring·设计模式
Refrain_zc1 小时前
Android TV 语音消息实战:遥控器 PCM 录音失真修复与扬声器强制播放方案
java
Stick_ZYZ1 小时前
从“能调用工具”到“能稳定执行任务”:Agent 工程化的下一步
java·人工智能·后端·spring·ai
代码中介商2 小时前
C++四大设计模式:单例、工厂、观察者、策略
java·c++·设计模式
宋志宗2 小时前
从三层架构到清晰边界:一套更适合复杂 Java 服务的分层方法
java