大家好,我是网域小星球。
本篇是 C++ 面试核心最后一篇,覆盖继承、多态、this 指针、深浅拷贝、三大特性,全部是 C++ 开发岗必问手撕考点。学完这 4 篇,足以应对 C++ 初试、笔试、基础面试提问,代码可直接在 VS2022 运行。
目录
[二、this 指针(面试高频基础)](#二、this 指针(面试高频基础))
[1. 核心概念](#1. 核心概念)
[2. 代码示例](#2. 代码示例)
[三、继承(C++ 三大特性之二)](#三、继承(C++ 三大特性之二))
[1. 继承作用](#1. 继承作用)
[2. 继承语法](#2. 继承语法)
[3. 公有继承代码示例](#3. 公有继承代码示例)
[4. 继承访问权限规则(面试必背)](#4. 继承访问权限规则(面试必背))
[5. 构造与析构继承顺序](#5. 构造与析构继承顺序)
[四、浅拷贝 & 深拷贝(面试超级高频)](#四、浅拷贝 & 深拷贝(面试超级高频))
[1. 浅拷贝](#1. 浅拷贝)
[2. 深拷贝](#2. 深拷贝)
[五、多态 & 虚函数(C++ 最难、面试必问)](#五、多态 & 虚函数(C++ 最难、面试必问))
[1. 多态概念](#1. 多态概念)
[2. 实现多态三个条件](#2. 实现多态三个条件)
[3. 虚函数 + 多态完整示例](#3. 虚函数 + 多态完整示例)
[4. 虚析构函数(面试大坑)](#4. 虚析构函数(面试大坑))
[六、C++ 三大特性 面试简答背诵版](#六、C++ 三大特性 面试简答背诵版)
[七、C++ 开发岗 高频简答汇总(直接背)](#七、C++ 开发岗 高频简答汇总(直接背))
一、本章学习目标
- 掌握 C++ 三大特性:封装、继承、多态完整概念
- 吃透继承语法、访问控制、菱形继承问题
- 理解 this 指针 面试常考原理
- 分清 浅拷贝 & 深拷贝(内存泄漏高频题)
- 掌握 多态、虚函数 核心原理与代码
二、this 指针(面试高频基础)
1. 核心概念
this 是成员函数隐含指针,指向当前调用该函数的对象。
- 每个非静态成员函数,都自带一个
this形参 - 作用:区分成员变量和局部同名变量、返回当前对象、操作自身成员
2. 代码示例
cpp
#include <iostream>
#include <string>
using namespace std;
class Person
{
public:
string name;
int age;
Person(string name, int age)
{
// this->name 代表成员变量
this->name = name;
this->age = age;
}
void show()
{
cout << this->name << " " << this->age << endl;
}
};
int main()
{
Person p("李四", 18);
p.show();
return 0;
}
面试常问
- this 指针存放在哪里?答:栈区,作为成员函数隐式形参传入。
- this 可以为空吗?答:可以,空 this 调用函数不崩溃,只要不解引用成员。
三、继承(C++ 三大特性之二)
1. 继承作用
复用代码、减少冗余、实现层级设计,子类复用父类成员与方法。
2. 继承语法
cpp
class 子类 : 继承方式 父类
{
// 子类独有成员
};
三种继承方式:
public公有继承(最常用)protected保护继承private私有继承
3. 公有继承代码示例
cpp
// 父类
class Animal
{
public:
void eat()
{
cout << "动物需要进食" << endl;
}
};
// 子类 公有继承
class Dog : public Animal
{
public:
void bark()
{
cout << "狗狗汪汪叫" << endl;
}
};
int main()
{
Dog d;
d.eat(); // 继承父类
d.bark(); // 自己独有
return 0;
}
4. 继承访问权限规则(面试必背)
- 父类
public→ 子类public - 父类
protected→ 子类protected - 父类
private→ 子类不可访问
5. 构造与析构继承顺序
构造:先父类,后子类 析构:先子类,后父类
四、浅拷贝 & 深拷贝(面试超级高频)
1. 浅拷贝
编译器默认拷贝构造,只拷贝地址,不拷贝堆内存内容。
- 多个对象共用同一块堆空间
- 析构时重复释放内存 → 程序崩溃
2. 深拷贝
手动写拷贝构造,重新开辟堆内存,每个对象独立资源。
完整对比代码
cpp
class Student
{
public:
char* msg;
// 构造:堆内存申请
Student()
{
msg = new char[20];
}
// 浅拷贝(默认)
//Student(const Student& s) = default;
// 深拷贝(手写)
Student(const Student& s)
{
msg = new char[20]; // 重新开空间
strcpy(msg, s.msg);
}
~Student()
{
delete[] msg;
}
};
面试标准答案
- 浅拷贝:只拷贝指针地址,资源共享,容易重复释放内存。
- 深拷贝:开辟新内存,资源独立,避免内存泄漏与崩溃。
五、多态 & 虚函数(C++ 最难、面试必问)
1. 多态概念
一个接口,多种实现父类指针 / 引用 指向子类对象,调用虚函数,执行子类重写逻辑。
2. 实现多态三个条件
- 必须有继承
- 父类函数加 virtual 虚函数
- 父类指针 / 引用 指向子类
3. 虚函数 + 多态完整示例
cpp
#include <iostream>
using namespace std;
class Animal
{
public:
// 虚函数
virtual void speak()
{
cout << "动物发声" << endl;
}
};
class Cat : public Animal
{
public:
// 重写
void speak() override
{
cout << "猫咪喵喵叫" << endl;
}
};
class Dog : public Animal
{
public:
void speak() override
{
cout << "狗狗汪汪叫" << endl;
}
};
// 多态接口
void test(Animal& a)
{
a.speak();
}
int main()
{
Cat c;
Dog d;
test(c);
test(d);
return 0;
}
运行结果:
cpp
猫咪喵喵叫
狗狗汪汪叫
4. 虚析构函数(面试大坑)
父类析构必须加 virtual,否则子类析构不执行,内存泄漏。
cpp
virtual ~Animal(){}
六、C++ 三大特性 面试简答背诵版
- 封装将属性私有化,对外提供接口,隐藏实现细节,提高安全性。
- 继承子类复用父类代码,降低冗余,实现代码复用。
- 多态父类引用指向子类,统一接口、不同实现,提高扩展性。
七、C++ 开发岗 高频简答汇总(直接背)
- 引用和指针区别?
- 重载和重写区别?
- 浅拷贝深拷贝区别?
- 多态实现原理?
- 虚函数作用?
- 构造、析构能否为虚函数?
- this 指针是什么?
1. 引用 和 指针 的区别
- 引用是变量别名,无独立内存;指针是独立变量,存储地址,占用空间。
- 引用必须初始化,且不可变更指向;指针可以不初始化、可随意改指向。
- 无空引用;存在空指针、野指针。
- 引用更安全简洁;指针更灵活,可用于跨函数修改、动态内存。
- 引用底层依旧是指针,但语法层面屏蔽了风险。
2. 重载 和 重写(覆盖)区别
重载(overload)
- 同一作用域、函数名相同、参数列表不同
- 编译期绑定,与返回值无关
- 属于静态多态
重写(override)
- 发生在继承关系中
- 子类重写父类 virtual 虚函数
- 函数名、参数、返回值完全一致
- 运行时绑定,实现动态多态
3. 浅拷贝 与 深拷贝 区别
- 浅拷贝:只拷贝指针地址,堆内存资源共享,析构重复释放导致崩溃。
- 深拷贝:手动开辟新堆空间,拷贝内容,每个对象资源独立。
- 类中有
new动态成员时,必须自己实现深拷贝。
4. 多态的实现原理
- 必须满足三大条件:继承 + 虚函数 + 父类指针 / 引用指向子类
- 含有虚函数的类,会生成虚函数表 (vtable)
- 对象内存在虚表指针 (vptr)
- 程序运行时通过 vptr 查找虚表,调用子类重写的函数
- 实现运行时多态
5. 虚函数作用
- 实现多态,父类统一接口,子类不同实现。
- 继承场景中,通过父类指针正确调用子类方法。
- 虚析构保证子类析构函数正常执行,避免内存泄漏。
6. this 指针是什么
- this 指针是非静态成员函数的隐含形参。
- 指向当前正在调用成员函数的对象。
- 用于区分局部变量与成员变量、返回当前对象。
- 存放于栈上,由编译器自动传递。
7. 构造函数、析构函数 能否是虚函数?
① 构造函数 不能 是虚函数
原因:
- 虚函数依赖 虚表指针 vptr。
- vptr 在构造函数执行完毕后才会初始化。
- 构造阶段对象还未完整创建,没有虚表,无法实现虚函数调用。
② 析构函数 可以 是虚函数,并且建议写为虚析构
场景:当父类指针指向子类对象时:
- 如果析构非虚 → 只调用父类析构,子类资源不释放,内存泄漏
- 如果析构为虚 → 触发多态,先析构子类,再析构父类
八、本篇总结
- this 指针是对象内置隐式指针,解决成员同名问题;
- 继承实现代码复用,必须注意构造析构顺序;
- 浅拷贝共享堆内存会崩溃,深拷贝手动开空间;
- 虚函数 + 继承 + 父类指针 = 多态;
- 虚析构防止继承场景内存泄漏;