C++类的简单介绍
一、构造函数
-
默认构造函数
-
触发场景:对象默认初始化、值初始化、构造数组元素
-
编译器生成规则:若未定义任何构造函数则自动生成
-
=default
:显式要求编译器生成默认版本 -
=delete
:禁止默认构造 -
必须自定义的场景:
-
类包含
const
成员或引用成员 -
存在不可默认构造的成员对象
-
-
-
构造函数的初始化与赋值
-
初始化列表:
-
必须使用的情况:
const
成员、引用成员、无默认构造函数的类类型成员 -
初始化顺序:按成员声明顺序,与初始化列表顺序无关
-
-
效率对比:初始化列表直接构造,赋值方式=构造+拷贝赋值
-
class Box {
public:
Box() = default; // 显式要求编译器生成默认构造
Box(int s) : size(s) {} // 自定义构造函数
private:
int size{0};
};
int main() {
Box b1; // 调用默认构造
Box b2{}; // 值初始化
Box arr[3]; // 数组元素默认构造
}
-
委托构造函数
-
C++11特性:一个构造函数调用同类的其他构造函数
class MyClass { MyClass(int a) : x(a) {} MyClass() : MyClass(0) {} // 委托构造 };
-
-
类型转换与
explicit
-
隐式转换规则:单参数构造函数定义转换规则
-
explicit
作用:禁止隐式转换,强制显式调用 -
典型应用场景:智能指针、
std::vector
的单参数构造函数
-
class Date {
public:
Date(int d) : day(d) {} // 允许隐式转换
explicit Date(string s) { ... } // 禁止隐式转换
};
void printDate(Date d) { ... }
int main() {
printDate(25); // 合法:Date(25)隐式转换
printDate("2023-01-01"); // 错误:explicit构造函数需显式转换
printDate(Date("2023-01-01")); // 正确
}
二、类的封装
-
实现机制
-
访问控制:
public
/private
/protected
-
接口暴露:通过公有成员函数操作私有数据
-
封装的意义:
-
数据保护
-
接口稳定性
-
实现与接口解耦
class BankAccount { public: void deposit(int amount) { if(amount > 0) balance += amount; } int getBalance() const { return balance; } private: int balance{0}; // 数据私有化 }; int main() { BankAccount acc; acc.deposit(100); // 通过公有接口操作 // acc.balance = 1000; // 错误:私有成员无法访问 }
-
-
-
class
vsstruct
-
唯一区别:默认访问权限(
class
默认private
,struct
默认public
) -
使用惯例:
-
struct
用于纯数据聚合 -
class
用于需要封装行为的对象// class默认private class PointClass { int x; // 默认private public: int y; }; // struct默认public struct PointStruct { int x; // 默认public private: int y; };
-
-
三、特殊成员
-
可变数据成员(
mutable
)-
允许在
const
成员函数中修改 -
典型应用:缓存、互斥锁、引用计数
class Cache { public: int getValue() const { accessCount++; // 允许修改mutable成员 return cachedValue; } private: int cachedValue; mutable int accessCount{0}; };
-
-
静态成员
-
静态数据成员:
-
类内声明 + 类外定义(C++17支持类内初始化)
-
生命周期:程序运行期间
-
-
静态成员函数:
-
无
this
指针,只能访问静态成员 -
调用方式:
ClassName::func()
-
-
四、类声明与定义
-
前向声明
-
使用场景:解决循环依赖、减少头文件包含
-
限制:只能定义指针/引用,不能访问成员
class B; // 前向声明 class A { public: B* pb; // 允许定义指针 void func(B&); }; class B { public: A* pa; };
-
-
字面值常量类
-
要求:
-
所有成员都是字面类型
-
至少一个
constexpr
构造函数 -
成员初始值必须为常量表达式
class ConstExprDemo { public: constexpr ConstExprDemo(int x) : val(x) {} constexpr int getVal() const { return val; } private: int val; }; int main() { constexpr ConstExprDemo c(42); int arr[c.getVal()]; // 用于编译期常量 }
-
-
-
聚合类
-
定义条件(C++17前):
-
所有成员
public
-
无用户定义构造函数
-
无基类、无虚函数
-
-
初始化方式:
MyClass obj = {val1, val2};
// C++17前聚合类 struct Aggregate { int id; string name; }; int main() { Aggregate a = {1, "Alice"}; // 聚合初始化 }
-
五、类的作用域
-
名字查找规则
-
成员函数内名字查找顺序:局部作用域 → 类作用域 → 外围作用域
-
类外定义成员函数时的作用域限定:
ClassName::
class ScopeTest { public: void func(int x) { x = 0; // 参数x隐藏成员变量 this->x = x; // 使用this访问成员 } private: int x{0}; };
-
-
成员隐藏与覆盖
-
局部变量隐藏成员变量:使用
this->
访问成员 -
派生类成员隐藏基类同名成员
-
六、友元机制
-
友元类
-
单向授权:友元类可访问当前类的私有成员
-
典型应用:迭代器类访问容器私有数据
class Storage { friend class Logger; // 友元类 private: string secret{"Confidential"}; }; class Logger { public: void log(const Storage& s) { cout << s.secret; // 访问私有成员 } };
-
-
友元函数
-
非成员友元函数:需在类内声明,类外定义
-
友元成员函数:需注意声明顺序依赖
class Window; class Controller { public: void resetWindow(Window& w); }; class Window { friend void Controller::resetWindow(Window&); private: int state{0}; }; void Controller::resetWindow(Window& w) { w.state = 0; // 访问Window私有成员 }
-
-
友元的特性
-
不可传递性:友元的友元不是我的友元
-
不可继承性:基类友元不是派生类友元
-
七、类定义的两阶段处理
-
编译阶段划分
-
第一阶段:处理成员声明(包括类型检查)
-
第二阶段:处理成员函数体(此时类已完整定义)
class TwoPhase { public: typedef int value_type; value_type process() { return data; // 正确:第二阶段处理函数体 } private: value_type data{0}; };
-
-
影响场景
-
成员函数体内可使用类后续声明的成员
-
成员默认参数初始化顺序依赖
-
八、高级特性补充
-
拷贝控制成员
-
拷贝构造函数、拷贝赋值运算符
-
移动构造函数、移动赋值运算符(C++11)
-
析构函数
class String { public: String(const char* s); // 构造函数 String(const String&); // 拷贝构造 String& operator=(const String&); // 拷贝赋值 ~String() { delete[] data; } // 析构函数 private: char* data; };
-
-
成员函数特性
-
const
成员函数:承诺不修改对象状态 -
引用限定符(C++11):
&&
或&
限制调用对象的值类别
-
-
嵌套类与局部类
-
嵌套类访问权限:遵循常规访问控制规则
-
局部类限制:不能定义静态成员、不能访问非静态局部变量
-
九、设计模式关联
-
RAII(资源获取即初始化)
-
通过构造函数获取资源,析构函数释放资源
-
-
PIMPL(Pointer to Implementation)
-
使用不透明指针隐藏实现细节
-
知识图谱总结
核心概念 | 关键要点 | C++11/17增强 |
---|---|---|
构造函数家族 | 默认/拷贝/移动/委托构造 | =default , 委托构造 |
封装与访问控制 | public /private /友元机制 | friend 作用域优化 |
静态成员 | 类内初始化、生命周期管理 | 内联静态成员(C++17) |
类型转换控制 | explicit 关键字 | 多参数explicit (C++20) |
特殊类设计 | 字面值常量类、聚合类 | 聚合类扩展(C++17) |