33.C++核心语法知识总结

33.总结


33.1 知识点

学习的主要内容

强调



33.2 核心要点速览

面向对象脚本概念

  • 核心理念:万物皆对象,用类抽象特征和行为。

封装

类和对象

核心要点 说明
类的定义 class声明,包含成员变量、构造/析构函数、成员方法,是对象的模板。
对象实例化 - 栈上:ClassName obj;
- 堆上:ClassName* ptr = new ClassName();
内存分布 类定义在代码段,对象实例存储在栈或堆,成员变量占用实际内存。

访问修饰符(3P)

修饰符 作用 访问范围
public 公共成员,类内外均可访问。 类内、类外、子类(继承时)
private 私有成员,仅类内部可访问(默认修饰符)。 仅限类内
protected 保护成员,类内和子类可访问。 类内、子类(继承时)

成员方法

核心要点 说明
声明与定义 - 声明在类内,定义可在类内(内联)或类外(.cpp)。
内联函数 inline修饰,编译时插入代码,减少函数调用开销,适合短函数。
this指针 指向当前对象,用于区分参数与成员变量(如this->age = age;)。

构造函数与析构函数

类型 构造函数 析构函数
声明 ClassName(); / ClassName(int a); ~ClassName();
作用 初始化对象成员,可重载。 释放对象资源(如堆内存),不可重载。
调用时机 实例化对象时自动调用。 对象释放时自动调用(栈对象出作用域/堆对象delete)。

静态成员

类型 静态成员变量 静态成员函数
声明 static int count; static void func();
初始化 .cpp中定义:int ClassName::count = 0; 直接定义在类内或.cpp,无this指针。
访问方式 ClassName::count / obj.count ClassName::func() / obj.func()
特性 所有对象共享,生命周期贯穿程序运行。 不能访问非静态成员,属于类而非对象。

下面是优化后的表格,展示了 C++ 中 const 成员变量、const 成员函数和 const 修饰函数参数的详细对比:

const 成员变量 vs const 成员函数

特性 const 成员变量 const 成员函数
声明示例 const int age = 18;
const int id;(需初始化列表)
void print() const;
初始化规则 - 声明时直接赋值
- 构造函数初始化列表赋值
- 在函数声明和定义处均需加 const 后缀
修改限制 初始化后不可修改(即使在构造函数体内也不可赋值) - 不可修改非 mutable 成员变量
- 可修改 mutable 成员变量
调用限制 无特殊限制 - 只能被 const 对象调用
- 非 const 对象可调用
典型用途 - 固定常量值(如 PI)
- 对象标识(如 ID)
- 访问器(getter)方法
- 不修改状态的操作

const 修饰函数参数

参数类型 语法示例 限制 作用
基本类型 void func(const int i); 函数内不可修改参数值(值传递) 防止意外修改,无实际数据保护(值拷贝)
指向常量的指针 void func(const int* ptr); 可改指针指向,不可改指向的值 保护数据不被修改,允许指针重定向
指针常量 void func(int* const ptr); 不可改指针指向,可改指向的值 固定指针指向,允许修改数据
指向常量的指针常量 void func(const int* const ptr); 不可改指针指向和指向的值 完全保护数据和指针指向
常量引用 void func(const int& ref); 不可修改引用对象,避免拷贝开销 高效传递对象,保护数据不被修改

友元

类型 友元函数 友元类 友元成员函数
声明 friend void func(Class& obj); friend class FriendClass; friend void FriendClass::func(Class& obj);
本质 全局函数,需在类中声明为friend 整个类被声明为友元,所有成员可访问 某类的成员函数被声明为友元,允许访问
作用 允许单个函数访问类的私有/保护成员 允许整个FriendClass类访问另一个类的私有/保护成员 允许某个类的特定成员函数访问私有/保护成员
访问范围 函数内可访问目标类的私有/保护成员 友元类的所有成员函数均可访问目标类成员 仅被声明的成员函数可访问目标类成员
调用方式 直接调用(全局函数) 通过友元类对象调用成员函数 通过友元类对象调用被声明的成员函数
注意事项 - 非类成员,需通过对象参数访问
- 无this指针
- 友元关系单向(A是B的友元≠B是A的友元)
- 不继承
- 需明确作用域(FriendClass::func
- 属于友元类的成员
代码示例
class A {
friend void f(A& a);
};
void f(A& a) { a.privateMember; }

class A {
friend class B;
};
class B {
void access(A& a) { a.privateMember; }
};

class A {
friend void B::access(A& a);
};
class B {
void access(A& a) { a.privateMember; }
};

嵌套类

核心要点 说明
定义 在类内声明的类,如class Outer { class Inner { ... }; };
访问限制 受外层类访问修饰符影响(public可外部使用,private仅限外层类内)。
独立性 与外层类相互独立,可定义自己的成员和方法。

命名空间

核心要点 说明
作用 避免命名冲突,封装相关功能(如namespace Math { int add(); })。
声明 namespace Name { int val; void func(); }
使用 - 限定访问:Name::val
- 导入:using namespace Name;
嵌套 可多层嵌套,如namespace A::B::C { ... },用A::B::C::func();访问。

运算符重载

核心要点 说明
语法 返回类型 operator符号(参数列表),如Point operator+(const Point& p);
类型 - 成员函数:左操作数为类对象
- 非成员函数:可定义其他类型左操作数
常见重载 + - * / == != ++ -- [] ()等,不可重载. :: ?:等符号。
注意 需保持运算符原始语义,避免滥用,建议成对实现关系运算符(如==!=)。

继承

继承的基本规则

特性 说明 注意
“是一个”关系 子类获得父类字段、方法、属性;不含构造、析构、友元 支持多继承(C++)、传递性(前提是访问权限允许)
语法 class 子 : 访问修饰 父 { … }; 访问修饰符决定基类成员在子类中的新可见性
同名隐藏 子类定义同名成员会隐藏基类所有同名重载 父类::member 或在子类写 using 父类::member; 恢复访问
禁止继承 C++ 用 final,C# 用 sealed 只对类生效,不影响已有成员访问

继承方式与访问控制

父类原级别 public 继承后 protected 继承后 private 继承后
public public protected 不可访问
protected protected protected 不可访问
private 不可访问 不可访问 不可访问

继承后的构造函数和析构函数

阶段 执行顺序 要点/注意
构造 ① 递归调用顶层基类
② 构造子类成员(字段/对象,声明顺序)
③ 执行子类自身构造体
默认调用基类无参构造;若无,则初始化列表必须显式调用带参基构造;C++ 可 using 父::父; 引入基类构造
析构 ① 执行子类自身析构
② 析构子类成员
③ 调用各级基类析构
析构不继承,顺序与构造相反

多重继承

特性 说明 关键点/注意
语法 class 子 : 父1, 父2 { … }; 构造按声明顺序调用;析构逆序;若同名需 父::成员 指定
同名二义 多个父有同名成员 必须 父类::member

菱形继承 & 虚继承

类型 问题或方案 关键点/注意
普通菱形继承 B、C 各继 A ⇒ D 得到两份 A 成员访问二义、内存冗余
虚继承 class B : virtual public A D 只保留一份 A;虚基类由最底层派生类负责构造(中间 A(...) 不生效);访问时需额外偏移/指针跳转,开销略增

继承中的友元 & 运算符重载

特性 继承行为 关键点/注意
友元 (friend) 不会被继承 父子友元关系独立;子类私有/保护成员仍不可由父友元访问
运算符重载 (operator) 会被继承 子类可直接使用父类重载运算符

里氏替换原则

场景 表现 关键点/注意
栈上替换 GameObject obj = Player(); 对象切片(子类部分丢失)、不可再转回子类,不推荐
堆上替换 GameObject* p = new Player(); 不切片,可 dynamic_cast<子*>(父*) 安全下转;常用于多态场景

多态

虚函数与多态实现

特性 说明 关键点/注意事项
多态本质 同一父类的不同子类对象,执行相同方法时表现不同行为(运行时多态) 通过虚函数(virtual)和重写(override)实现
虚函数声明 virtual 返回值 函数名(参数) {}(需在父类声明,子类用override重写) - virtual不可省略,override建议保留(编译期检查重写正确性)
- 重写时参数/返回值必须与父类一致
保留父类逻辑 子类重写函数中用父类名::函数名()显式调用父类实现 Son::Test() { Father::Test(); cout << “子类逻辑”; }
多态调用场景 父类指针/引用指向子类对象时,自动调用子类重写方法(堆上里氏替换) 栈上对象切片会丢失多态性(仅调用父类方法)

虚析构函数

特性 说明 核心作用
必要性 父类析构函数设为虚函数,确保通过父类指针释放子类对象时调用子类析构。如果父类没有设置子类析构不会调用。只需保证最上层父类有虚析构即可。 避免子类资源未释放(如堆内存)导致内存泄漏
执行顺序 子类析构 → 父类析构(与构造顺序相反) 多层继承时只需顶层基类析构为虚函数即可
栈上调用 栈上对象按正常析构顺序调用(先子后父),但切片时子类特有析构可能不执行 Father* f = new Son(); delete f; // 正确调用Son析构
Father f2 = Son(); // 切片,仅调用Father析构

抽象类与纯虚函数

特性 说明 规则
抽象类定义 包含至少一个纯虚函数的类(不能直接实例化,仅作基类) class Shape {
virtual void draw() = 0; // 纯虚函数
};
纯虚函数语法 virtual 函数() = 0;(无函数体,子类必须重写) 子类未实现纯虚函数则自身也为抽象类
应用场景 定义接口规范(如图形基类、游戏对象基类) 抽象类可包含普通函数和成员变量,子类继承后需实现所有纯虚函数

禁止重写(final关键字)

特性 说明 语法示例
禁止类继承 class 类名 final {};(防止类被继承) class FinalClass final {};
禁止函数重写 虚函数后加finalvirtual void func() override final; class Father {
virtual void func() final; // 子类不可重写
};

虚函数表(V-Table)

特性 说明 底层原理
本质 存储虚函数指针的数组,每个含虚函数的类对应一张表 类的所有对象共享虚函数表,对象含虚表指针(vptr)指向该表
内存位置 存储在数据段/常量段(全局共享) 对象sizeof会增加一个指针大小(64位8字节)
多继承实现 每个父类对应一张虚表,子类对象含多个vptr指向各父类虚表 子类虚函数放入第一个父类虚表中(主流编译器实现)

面向对象关联知识点

接口(C++模拟实现)

核心要点 说明 实现方式
本质 行为的抽象规范,C++中通过纯虚函数的抽象类模拟接口 class IFly { virtual void Fly()=0; };(仅含纯虚函数的抽象类)
命名规范 接口类名前缀加I(如IFly class IWalk { virtual void Walk()=0; };
继承与实现 子类继承接口类后必须实现所有纯虚函数 class Bird : public IFly { void Fly() override { ... } };
应用场景 统一管理不同类型但有相同行为的对象(如飞机、鸟、超人都实现IFly接口) IFly* obj[2] = {new Plane(), new Bird()};(里氏替换原则应用)

多继承同名虚函数

核心要点 说明 实现规则
同名处理 多继承时父类若有同名虚函数,子类只需重写一次即可覆盖所有父类版本 class Father { virtual void Eat(); };
class Mother { virtual void Eat(); };
class Son : public Father, public Mother {
void Eat() override { Father::Eat(); Mother::Eat(); }
}
底层原理 多个父类虚函数表中的该函数指针均指向子类重写的函数 子类虚函数表中该函数地址统一指向子类实现,调用时自动分发

空类型的内存占用

核心要点 说明 示例
空类大小 空类/结构体占1字节(确保对象有唯一内存地址) sizeof(EmptyClass) → 1(64位/32位平台均为1)
继承优化 子类包含成员时,空基类的1字节会被优化(不额外占用空间) class Base {}; // sizeof=1
class Derived : Base { int i; }; // sizeof=4(Base的1字节被优化)
含虚函数空类 包含虚函数的空类占8字节(64位平台,虚表指针大小) class VirtualEmpty { virtual void Fun(); };sizeof=8(64位)

结构体与类的区别

核心要点 结构体(struct) 类(class)
默认访问权限 public(成员和继承默认均为public) private(成员和继承默认均为private)
设计初衷 侧重数据集合(如坐标、配置数据) 侧重面向对象封装(数据+行为)
继承语法 struct Son : Father {};(默认public继承) class Son : Father {};(默认private继承)
应用场景 简单数据结构(如struct Point { int x,y; } 复杂对象(如class Player { int hp; void Attack(); }

字符数组与string对比

核心要点 字符数组(char[]) string类
内存管理 固定长度,需手动管理(易越界) 动态扩容,自动管理内存
安全性 无边界检查,易导致缓冲区溢出 有边界检查,安全系数高
常用操作 需要调用C函数(如strcat_sstrcpy_s 支持运算符重载(++=)和成员函数(appendsubstr
空终止符 需手动保证\0终止,否则打印乱码 自动管理终止符,size()返回有效长度
推荐场景 底层开发、嵌入式(空间敏感) 日常字符串处理、C++标准库交互


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏