C++(20)—类和对象(下) ⑤内部类
文章目录
- 一、内部类的定义与基本特性
- 二、内部类的声明与访问权限
- 三、内部类的友元特性
- 1. 默认友元关系
- 2. 访问外部类成员的限制
- 四、内部类的内存与生命周期
- 1. 存储位置
- 2. 生命周期
- 五、内部类的使用场景
- 1. 紧密关联的类设计
- 2. 隐藏实现细节
- 六、内部类与友元类的对比
- 七、总结
一、内部类的定义与基本特性
内部类(Nested Class) 是指定义在另一个类内部的类。它与外部类的关系类似于“容器”与“内容”,但内部类本身是一个完全独立的类,仅受外部类的作用域和访问限定符限制。其核心特性如下:
二、内部类的声明与访问权限
1. 声明方式
内部类可以在外部类的public、protected或private区域声明,访问权限决定了其可见范围:
public内部类:可在外部类之外直接使用(需通过作用域运算符::)。
private内部类:仅能在外部类内部使用。
示例代码:
class Outer {
public:
class PublicInner { // 公有内部类
public:
void AccessOuter(Outer& outer) {
cout << outer._privateVar << endl; // 访问外部类私有成员
}
};
private:
class PrivateInner { // 私有内部类(仅Outer内部可用)
public:
void ShowSecret() { cout << "Secret!" << endl; }
};
int _privateVar = 42;
};
三、内部类的友元特性
1. 默认友元关系
内部类默认是外部类的友元类,因此可以直接访问外部类的所有成员(包括私有成员),无需显式声明friend。
class A {
private:
static int _k;
int _h = 1;
public:
class B { // B是A的友元类
public:
void foo(const A& a) {
cout << _k << endl; // 直接访问静态私有成员
cout << a._h << endl; // 通过对象访问非静态私有成员
}
};
};
int A::_k = 1;
int main() {
A::B b; // 实例化内部类
A aa;
b.foo(aa); // 输出:1 和 1
return 0;
}
2. 访问外部类成员的限制
静态成员:可直接访问(如_k)。
非静态成员:必须通过外部类对象访问(如a._h)。
四、内部类的内存与生命周期
1. 存储位置
内部类的对象与普通类对象一样,存储在栈或堆中。
外部类对象不包含内部类对象,二者内存独立。
2. 生命周期
内部类对象的生命周期由其作用域或new/delete控制,与外部类对象无关。
静态成员变量仍存储在静态区,与类生命周期一致。
五、内部类的使用场景
1. 紧密关联的类设计
当两个类高度耦合,且一个类(内部类)主要为另一个类(外部类)服务时,使用内部类可增强封装性。
示例:迭代器模式中的Iterator类作为容器的内部类。
class List {
public:
class Iterator { // 内部迭代器类
public:
Iterator(Node* node) : _current(node) {}
// 迭代器操作...
private:
Node* _current;
};
Iterator Begin() { return Iterator(_head); }
private:
Node* _head;
};
2. 隐藏实现细节
通过将辅助类声明为private内部类,可完全隐藏其实现,避免被外部误用。
示例:数据库连接池中的连接管理器。
class ConnectionPool {
private:
class Connection { // 私有内部类,外部不可见
public:
void Connect() { /* ... */ }
};
public:
void Initialize() {
Connection conn;
conn.Connect();
}
};
六、内部类与友元类的对比
七、总结
内部类是C++中一种强大的封装工具,通过默认友元关系和访问权限控制,能够实现高内聚的类设计。合理使用内部类可以:
增强代码可读性和组织性;
隐藏实现细节,提升封装性;
替代友元类,简化协作逻辑。
然而,内部类的滥用可能导致代码结构复杂化。开发者应在封装需求与代码简洁性之间找到平衡,遵循“最小暴露原则”,让内部类真正成为提升代码质量的利器。