C++ 允許在函數內部定義類(區域類),也允許在類內部定義類(嵌套類/內部類)。兩者雖然語法相似,但語義、作用域規則、訪問權限有本質區別。本文參考《C++ 程式設計思想》《高質量程式設計指南》及網絡資料,系統整理相關知識點。
C++ 區域類對象沒有外部函數/類對象的指針,不能訪問外部非靜態成員;
Java 非靜態內部類對象持有外部類對象引用,能自由訪問外部非靜態成員。
int a; // 全局變量
void fun() {
static int s; // 靜態局部變量,區域類可訪問
class A {
public:
void init(int i) { s = i; } // 只能訪問靜態/全局變量
};
A m; m.init(10);
}
class Interface { public: virtual void Fun() = 0; };
template <class T, class P>
Interface* MakeAdapter(const T& obj, const P& arg) {
int x; // 局部變量,區域類不可直接訪問
class Local : public Interface {
public:
Local(const T& o, const P& a) : obj_(o), arg_(a) {}
virtual void Fun() { x = 100; obj_.Call(arg_); } // 錯誤:不能訪問 x
private:
T obj_; P arg_;
};
return new Local(obj, arg);
}
註:上例中 `x` 無法被 `Local` 訪問,若需使用需改為 `static int x;` 或通過構造函數傳入。
Outer::Inner 形式訪問,且受訪問權限控制。隱藏類名,減少全局標識符污染,限制用戶直接構造對象,提高封裝性,強調「主從」關係。
class A {
public:
class B { // 嵌套類
public:
void func(); // 可在類外定義
private:
int b_data;
};
void f();
private:
int a;
};
// 類外定義嵌套類成員函數
void A::B::func() { /* ... */ }
以下兩種寫法在語義上幾乎等價:
// 寫法 1:嵌套
class A { public: class B { ... }; private: int a; };
// 寫法 2:分離
class A { public: void f(); private: int a; };
class B { public: ... private: ... };
嵌套類僅提供名字隱藏和邏輯分組,不改變類之間的訪問關係。
| 特性 | 區域類 | 嵌套類 |
|---|---|---|
| 定義位置 | 函數內部 | 類內部 |
| 作用域 | 僅限該函數 | 限於外圍類 |
| 成員函數定義 | 必須在類內 | 可在類外 |
| 訪問外部變量 | 僅靜態/全局 | 無隱含權限(需傳遞引用) |
| 靜態成員 | 僅靜態數據成員(外部初始化),無靜態函數成員 | 正常支援 |
| 主要用途 | 封裝函數內邏輯、實現介面適配 | 隱藏實現細節、組織相關類型 |