一、首先我們要知道c++中類與類之間有哪些關係。

1.繼承

  繼承指的是一個類繼承另外的一個類繼承的類叫做子類,被繼承的類叫做父類。

語法形式為:

class A{
};
class B:public A{
};
其中A為父類,B為子類,public 是繼承方式,具體的內容不再多說,可參考相關的c++書籍。

2.實現

    實現講的是c++中面向物件的“介面”,“介面”是java中的重點,在c++中的介面主要通過純虛擬函式實現。

class A{
public:
   virtual void func();
};
class B:public A{
void func(){
   }
};
類A中的函式func()為純虛擬函式,沒有函式體,在繼承它的函式中寫出func()的具體實現。

3.依賴

    C++語法中,通過將一個類作為另一類方法的引數的形式實現兩個類之間的依賴關係

class A{
};
class B{
public:
   void func(A a){};
};
A型別的物件作為B類中函式的引數。

4.聚合

    在C++語法中,通過類的指標來實現聚合

class A{
};
class B{
public:
   A a[5];
};

5.關聯

    C++中,通過定義其他類指標型別的成員來實現關聯。

class A{
};
class B{
public:
   A *a;
};

6.組合

    組合是將一個物件(部分)放到另一個物件裡(組合)。相比"聚合",組合是一種強所屬關係,組合關係的兩個物件往往具有相同的生命週期,被組合的物件是在組合物件建立的同時或者建立之後建立,在組合物件銷燬之前銷燬。一般來說被組合物件不能脫離組合物件獨立存在,而且也只能屬於一個組合物件在C++語法中,使用在一個類中包含另外一個類型別的成員來實現組合。

class A{
};
class B{
public:
   A a;
};
、組合的特殊情況。
class B;
class A{
public:
B b;
};
class B{
public:
   A a;
};

第一行的class B 是前置宣告,因為B型別還沒有定義,要“告訴”編譯器 B 是什麼。但是,這樣編譯器就能編譯通過了麼?

還是不行的。為什麼呢?

編譯器在編譯時是一字一句的編譯的,我們來簡單看一下他的編譯過程:

首先,它“看到”class B,知道了B是一種“類“型別。接著 是A類的定義,在定義A類時,A類中有一個B型別的變數,編譯器要知道B型別是什麼樣的才能繼續編譯A,只好轉去編譯B(編譯器要為A分配記憶體就要知道A佔用記憶體空間的大小,也就是要知道B的大小),結果B中也有A的物件而A還沒編譯完整。編譯器知道這樣下去只會沒完沒了,所以它撂挑子不幹了,返回一個編譯錯誤就是A沒有定義(好像是A,要麼就是B,按理應該是A,記不清了疑問),總之會編譯錯誤。

那我們怎麼解決這樣的問題呢?

class B;
class A{
publc:
B b;
};
class B{
public:
   A *a;
};
仔細觀察發現將其中一個類的物件改為了指標型別,而指標型別佔用的空間是確定的,這樣編譯器就知道的B的佔用空間大小,從而可以編譯A。