在一個類中定義的類稱為嵌套類,定義嵌套類的類稱為外圍類。
定義嵌套類的目的在於隱藏類名,減少全局的標識符,從而限制用戶能否使用該類建立對象。這樣可以提高類的抽象能力,並且強調了兩個類(外圍類和嵌套類)之間的主從關系。下面是一個嵌套類的例子:
class A { public: class B { public: … private: … }; void f(); private: int a; }
其中,類B是一個嵌套類,類A是外圍類,類B定義在類A的類體內。
對嵌套類的若干說明:
1、從作用域的角度看,嵌套類被隱藏在外圍類之中,該類名只能在外圍類中使用。如果在外圍類的作用域內使用該類名時,需要加名字限定。
2、從訪問權限的角度來看,嵌套類名與它的外圍類的對象成員名具有相同的訪問權限規則。不能訪問嵌套類的對象中的私有成員函數,也不能對外圍類的私有部分中的嵌套類建立對象。
3、嵌套類中的成員函數可以在它的類體外定義。
4、嵌套類中說明的成員不是外圍類中對象的成員,反之亦然。嵌套類的成員函數對外圍類的成員沒有訪問權,反之亦然。國此,在分析嵌套類與外圍類的成員訪問關系時,往往把嵌套類看作非嵌套類來處理。這樣,上述的嵌套類可寫成如下格式:
class A
{
public:
void f();
private:
int a;
};
class B
{
public:
…
private:
…
};
由引可見,嵌套類僅僅是語法上的嵌入。
5、在嵌套類中說明的友元對外圍類的成員沒有訪問權。
6、如果嵌套類比較復雜,可以只在外圍類中對嵌套類進行說明,關於嵌套的詳細的內容可在外圍類體外的文件域中進行定義。
7、嵌套類可以訪問外圍類的靜態成員變量,即使它的訪問權限是私有的。
但是,如果一定要讓嵌套類訪問外圍類,我們要采取什么樣的辦法?實際上實現的方法應該有很多種,這里介紹一種參見com實現中實現內嵌類訪問外部類數據成員中所使用的方式,具體見《COM本質論》。
//嵌套類訪問外圍類中的成員變量
class GH_A{
const static int s_data = 20;
public:
int task_id;
class GH_B
{
public:
int attribute;
GH_A* parent;
GH_B(){
attribute = 5;
parent = (GH_A*)((char*)this-offsetof(GH_A,gh_b));
printf("外圍類的private型靜態變量:%d\n",s_data);
}
} gh_b;
};
//嵌套類訪問外圍類成員變量的示例
GH_A aaaa;
aaaa.gh_b.parent->task_id = 16;
printf("外圍類成員變量值被嵌套類訪問並修改之后的值:%d\n",aaaa.task_id);
aaaa.task_id = aaaa.gh_b.attribute;
printf("嵌套類訪問到外圍類成員變量值:%d\n",aaaa.gh_b.parent->task_id);
輸出結果:
這里,我們用到一個C++庫函數,原型是:
size_t offsetof( structName, memberName );
以下是MSDN上的一些介紹:
Parameters
- structName
-
Name of the parent data structure.
- memberName
-
Name of the member in the parent data structure for which to determine the offset.

offsetof returns the offset in bytes of the specified member from the beginning of its parent data structure. It is undefined for bit fields.
此外,再來介紹一下局部類
在一個函數體內定義的類稱為局部類。局部類中只能使用它的外圍作用域中的對象和函數進行聯系,因為外圍作用域中的變量與該局部類的對象無關。局部類不能被外部所繼承。在定義局部類時需要注意:局部類中不能說明靜態成員函數,並且所有成員函數都必須定義在類體內。在實踐中,局部類是很少使用的。下面是一個局部類的例子。
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& obj, const P& arg) : obj_(obj), arg_(arg) {} virtual void Fun() { x = 100; obj_.Call(arg_); } private: T obj_; P arg_; }; return new Local(obj, arg); }
參考:C++編程思想和網絡文章, MSDN.