Limesn
Limesn
发布于 2026-09-11 / 1 阅读
0

第二章 类与对象

1. 类与对象的基本概念

  • 什么是类,什么是对象?(用自己的话描述)
    • 类(Class):是一个蓝图、模板或自定义的数据类型。它定义了某类事物共有的属性(成员变量)和行为(成员函数)。它本身不占用实际的内存空间(除了类型信息)。
    • 对象(Object):是类的一个具体实例。根据类这个模板在内存中实际分配了空间,拥有具体的属性值。比如“人”是类,而“张三”是一个对象。

2. 权限修饰符

  • public的权限是什么? 公开的。类内部可以访问,类外部(通过对象)也可以直接访问。通常用于提供对外接口。
  • private的权限是什么? 私有的。只能在类的内部(成员函数中)或者友元中被访问。类外部无法直接访问,通常用于隐藏数据(封装)。
    (补充:还有一个protected,权限介于两者之间,类外部不能访问,但子类可以访问)

3. structclass 的区别

  • 在C++中,两者区别很小,主要在于默认的访问权限和默认的继承权限
    • struct 的默认访问权限和默认继承权限是 public
    • class 的默认访问权限和默认继承权限是 private

4. 构造函数 (Constructor)

  • 什么是构造函数?有什么作用? 函数名与类名相同,且没有返回类型(连void都没有)的特殊成员函数。作用是初始化对象的数据成员,分配资源等。
  • 什么时候会调用构造函数? 在创建对象时自动调用。包括:栈上创建对象、堆上 new 对象、创建临时对象、以及作为成员对象被包含在另一个类中初始化时。

5. 对象的大小

  • 一个对象的大小取决于什么? 取决于:
    1. 非静态成员变量的总大小(受内存对齐影响,可能会有padding填充)。
    2. 如果有虚函数,需要加上一个虚函数表指针(vptr)的大小(通常为8字节或4字节)。
    3. 注意:静态成员变量、成员函数、虚函数表本身不占用对象的内存空间。空类的大小通常为1字节。

6. 左值与右值

  • 什么是左值?什么是右值?
    • 左值(L-value):有明确的内存地址,有名字,表达式结束后依然存在的持久对象(如变量、数组元素、解引用的指针)。
    • 右值(R-value):没有名字,临时存在的值,表达式结束后就销毁(如字面量、临时对象、返回非引用类型的函数返回值)。
  • 什么样的引用可以绑定左值? 非常量左值引用(T&)只能绑定左值;常量左值引用(const T&)可以绑定左值(也是万能引用的一种形式)。
  • 什么样的引用可以绑定左值和右值? **常量左值引用(const T&既可以绑定左值,也可以绑定右值。
    *(补充:C++11引入的
    右值引用(T&&)*只能绑定右值)

7. 拷贝构造函数

  • 语法形式是什么?为什么? 形式:ClassName(const ClassName& other)。必须是引用传参,因为如果按值传参,实参传给形参时会再次调用拷贝构造,导致无限递归死循环。加const是为了能接收常量对象和临时对象。
  • 什么情况下会触发拷贝构造的调用?
    1. 用一个已存在的对象初始化新对象(A a = b;A a(b);)。
    2. 对象作为实参,以值传递的方式传给函数。
    3. 函数返回局部对象(以值方式返回,取决于编译器优化,未优化时会触发)。

8. 深拷贝与浅拷贝

  • 什么是深拷贝,什么是浅拷贝?
    • 浅拷贝:仅仅复制对象的所有成员变量的值(如果是指针,就只复制指针地址)。这会导致两个对象共享同一块堆内存,容易引发“双重释放(Double Free)”问题。默认生成的拷贝构造函数就是浅拷贝。
    • 深拷贝:在复制指针成员时,不是复制地址,而是重新在堆区分配一块新的内存,并将原指针指向的内容复制过去。这样两个对象各自拥有独立的资源,互不影响。

9. 析构函数 (Destructor)

  • 语法形式是什么? ~ClassName(),没有参数,没有返回值,不能重载,一个类只能有一个析构函数。
  • 析构函数一般用来干什么? 在对象生命周期结束时自动调用。主要用于清理资源,比如释放动态分配的堆内存(delete)、关闭文件句柄、释放网络连接等,防止内存泄漏。

10. this 指针

  • this是什么?this的本质是什么?
    • this 是当前对象的指针。
    • 它的本质是一个隐含的形参(编译器自动添加的),指向调用该成员函数的对象。在底层,它是 ClassName* const this(一个指针常量,即指向不能改变,但指向的内容可以改变)。静态成员函数没有 this 指针。

11. 赋值运算符重载函数

  • 语法形式是什么?为什么? ClassName& operator=(const ClassName& other)
    • 为什么返回引用 ClassName& 为了支持链式赋值(如 a = b = c),并且避免返回时调用一次拷贝构造。
    • 为什么参数是 const ClassName& 防止在赋值过程中修改原对象(const),且引用传参避免一次拷贝(&)。
  • 赋值运算符函数的本质是什么? 是对已存在的两个对象进行数据成员的覆盖和资源的重新分配。它与拷贝构造的区别在于:拷贝构造是在对象初始化时调用,而赋值运算符是在对象已经存在时调用。
    (注意点:在实现赋值运算符时,必须检查自我赋值 if (this != &other),并且如果是深拷贝,需要先释放原有的资源,再分配新资源)

这份提纲涵盖了C++面向对象编程最核心的基础知识点,非常适合用来准备面试或期末复习。如果有哪一部分需要更深入的原理解析(比如汇编层面的this传递或虚函数表),可以继续提问。