C++ 从 0 入门(三)|类与对象基础(封装、构造 / 析构函数,面试必考)

大家好,我是网域小星球。

本篇是 C++ 面向对象的核心开篇,也是 C++ 面试重中之重 ------ 类与对象基础。面试官几乎都会问封装、构造函数、析构函数的用法,甚至让手撕代码。本篇全程聚焦面试考点,不冗余、只讲核心,代码 VS2022 直接运行,吃透就能应对类与对象的基础面试提问。

目录

一、核心学习目标(面试导向)

二、类与对象的概念(面试基础题)

[1. 核心定义(面试直接答)](#1. 核心定义(面试直接答))

[2. 类的基础语法(必写)](#2. 类的基础语法(必写))

[3. 访问权限(封装的核心,面试必问)](#3. 访问权限(封装的核心,面试必问))

三、构造函数(面试必考,重中之重)

[1. 核心作用](#1. 核心作用)

[2. 构造函数的 3 个特点(面试必背)](#2. 构造函数的 3 个特点(面试必背))

[3. 构造函数的 3 种写法(笔试常考)](#3. 构造函数的 3 种写法(笔试常考))

[4. 面试坑点(必避)](#4. 面试坑点(必避))

四、析构函数(面试必考,与构造函数成对出现)

[1. 核心作用](#1. 核心作用)

[2. 析构函数的 3 个特点(面试必背)](#2. 析构函数的 3 个特点(面试必背))

[3. 析构函数用法(结合动态内存,面试常考)](#3. 析构函数用法(结合动态内存,面试常考))

[4. 面试考点(高频)](#4. 面试考点(高频))

[五、构造 / 析构函数的调用顺序(面试笔试题)](#五、构造 / 析构函数的调用顺序(面试笔试题))

六、本章核心总结(面试速记)

下期预告


一、核心学习目标(面试导向)

  1. 掌握 类与对象的概念(面向对象核心,面试必问)
  2. 理解 封装特性(C++ 三大特性之首,定义 + 用法)
  3. 熟练掌握 构造函数(写法、作用、面试常考重载)
  4. 熟练掌握 析构函数(写法、作用、内存释放逻辑)
  5. 避开构造 / 析构函数的常见面试坑点

二、类与对象的概念(面试基础题)

1. 核心定义(面试直接答)

  • 类(class):抽象的模板,定义对象的属性(成员变量)和行为(成员函数),不占用内存;
  • 对象:类的实例化,根据类模板创建的具体实体,占用内存;
  • 关系:类是对象的 "蓝图",对象是类的 "具体实现"(比如 "人类" 是类,"张三" 是对象)。

2. 类的基础语法(必写)

cpp 复制代码
#include <iostream>
#include <string>
using namespace std;

// 类的定义(class关键字)
class Person
{
// 访问权限(封装的核心)
public:  // 公有:类内、类外都能访问(常用)
    // 成员变量(属性)
    string name;
    int age;
    
    // 成员函数(行为)
    void showInfo()
    {
        cout << "姓名:" << name << ",年龄:" << age << endl;
    }

private: // 私有:只有类内能访问(封装核心,隐藏细节)
    string id; // 私有成员,类外无法直接访问
};

// 主函数:实例化对象
int main()
{
    // 方式1:默认实例化
    Person p1;
    p1.name = "张三"; // 公有成员,类外可访问
    p1.age = 20;
    p1.showInfo();   // 调用成员函数

    // 方式2:直接初始化
    Person p2 = {"李四", 22};
    p2.showInfo();

    return 0;
}

3. 访问权限(封装的核心,面试必问)

C++ 用访问权限实现封装,三种权限(牢记):

  1. public(公有):类内、类外均可访问(常用成员函数、对外暴露的属性);
  2. private(私有):只有类内可访问(核心属性,隐藏细节,比如身份证号、密码);
  3. protected(保护):类内可访问,子类可访问(后续继承章节讲解)。

面试考点:封装的作用?答:隐藏对象的核心细节,只对外暴露必要的接口,提高代码安全性、可维护性。


三、构造函数(面试必考,重中之重)

1. 核心作用

对象创建时自动调用,用于初始化对象的成员变量(避免成员变量为随机值),无需手动调用。

2. 构造函数的 3 个特点(面试必背)

  1. 函数名 和类名完全相同
  2. 没有返回值(连 void 都不写);
  3. 可重载(面试常考,多构造函数适配不同初始化场景)。

3. 构造函数的 3 种写法(笔试常考)

cpp 复制代码
#include <iostream>
#include <string>
using namespace std;

class Person
{
public:
    string name;
    int age;

    // 1. 无参构造函数(默认构造)
    Person()
    {
        name = "未知";
        age = 0;
        cout << "无参构造函数调用" << endl;
    }

    // 2. 有参构造函数(常用)
    Person(string n, int a)
    {
        name = n;
        age = a;
        cout << "有参构造函数调用" << endl;
    }

    // 3. 拷贝构造函数(面试高频,用一个对象初始化另一个对象)
    Person(const Person& p)
    {
        name = p.name; // 把p的name赋值给当前对象
        age = p.age;   // 把p的age赋值给当前对象
        cout << "拷贝构造函数调用" << endl;
    }

    void showInfo()
    {
        cout << "姓名:" << name << ",年龄:" << age << endl;
    }
};

int main()
{
    Person p1;        // 调用无参构造
    Person p2("张三", 20); // 调用有参构造
    Person p3 = p2;   // 调用拷贝构造(用p2初始化p3)

    p1.showInfo();
    p2.showInfo();
    p3.showInfo();
    return 0;
}

4. 面试坑点(必避)

  • 若手动写了有参构造,编译器 不会再自动生成无参构造(需手动写,否则报错);
  • 拷贝构造函数的参数,必须加 const(避免修改原对象),且必须是引用(避免无限递归);
  • 无参构造和默认构造的区别:无参构造是手动写的,默认构造是编译器自动生成的(若未写任何构造)。

四、析构函数(面试必考,与构造函数成对出现)

1. 核心作用

对象销毁时自动调用,用于释放对象占用的资源(比如动态内存、文件句柄),无需手动调用。

2. 析构函数的 3 个特点(面试必背)

  1. 函数名:~类名(波浪线 + 类名);
  2. 没有返回值,也没有参数(不能重载,只能有一个);
  3. 若未手动写,编译器会自动生成默认析构函数(但无法释放动态内存,面试常考)。

3. 析构函数用法(结合动态内存,面试常考)

cpp 复制代码
#include <iostream>
#include <string>
using namespace std;

class Person
{
public:
    string name;
    int* age; // 动态内存指针(面试常考场景)

    // 有参构造:申请动态内存
    Person(string n, int a)
    {
        name = n;
        age = new int(a); // 申请堆内存,存储年龄
        cout << "有参构造调用,申请内存" << endl;
    }

    // 析构函数:释放动态内存(必须手动写)
    ~Person()
    {
        if (age != nullptr) // 避免野指针
        {
            delete age;     // 释放堆内存
            age = nullptr;  // 置空,防止野指针
        }
        cout << "析构函数调用,释放内存" << endl;
    }

    void showInfo()
    {
        cout << "姓名:" << name << ",年龄:" << *age << endl;
    }
};

int main()
{
    Person p("张三", 20);
    p.showInfo();
    // 函数结束,对象p销毁,自动调用析构函数,释放内存
    return 0;
}

4. 面试考点(高频)

  • 析构函数为什么不能有参数?答:析构函数是对象销毁时自动调用的,无法手动传递参数,所以不能重载,只能有一个。
  • 什么时候必须手动写析构函数?答:当类的成员变量有动态内存(new 申请的内存)时,必须手动写析构函数释放,否则会造成内存泄漏。

五、构造 / 析构函数的调用顺序(面试笔试题)

牢记:先构造,后析构;构造顺序与对象创建顺序一致,析构顺序相反

示例代码(笔试常考):

cpp 复制代码
#include <iostream>
using namespace std;

class A
{
public:
    A() { cout << "A构造" << endl; }
    ~A() { cout << "A析构" << endl; }
};

class B
{
public:
    B() { cout << "B构造" << endl; }
    ~B() { cout << "B析构" << endl; }
};

int main()
{
    A a; // 先创建A,调用A构造
    B b; // 再创建B,调用B构造

    // 析构顺序:先析构后创建的B,再析构先创建的A
    return 0;
}

输出结果(面试直接答):A 构造 → B 构造 → B 析构 → A 析构


六、本章核心总结(面试速记)

  1. 类是模板(无内存),对象是实例(有内存),封装通过访问权限实现;
  2. 构造函数:类名相同、无返回值、可重载,对象创建时自动调用,用于初始化;
  3. 析构函数:~ 类名、无返回值、无参数,对象销毁时自动调用,用于释放资源;
  4. 动态内存必须在析构函数中释放,否则内存泄漏(面试重点);
  5. 构造顺序与对象创建一致,析构顺序相反(笔试常考)。

下期预告

C++ 从 0 入门(四)|类与对象进阶(继承、多态)+ 面试高频题(收官篇)

相关推荐
Dxy12393102161 小时前
Python如何去掉文本中的表情符号
开发语言·python
j_xxx404_2 小时前
Linux:缓冲区
linux·运维·c++·后端
studyForMokey2 小时前
【Android面试】架构模式专题
android·面试·架构
我真不是小鱼2 小时前
cpp刷题打卡记录29——矩阵置零 & 旋转图像 & 除了自身以外数组的乘积
数据结构·c++·算法·leetcode·矩阵
网域小星球2 小时前
C++ 从 0 入门(二)|引用与指针区别、函数重载、内联函数(面试高频)
开发语言·c++·面试·函数重载·内联函数·引用与指针区别
代码中介商2 小时前
C++ 多态与虚函数入门:从概念到规则
开发语言·c++
kyle~2 小时前
工业以太网协议---EtherCAT
开发语言·c++·网络协议·机器人·ros2
say_fall2 小时前
深入理解AVL树:平衡调整机制与性能优化实战
开发语言·数据结构·c++·学习
Ruihong2 小时前
你的 Vue 3 defineAsyncComponent(),VuReact 会编译成什么样的 React?
vue.js·react.js·面试