C 前置宣告

2021-09-20 23:36:06 字數 3358 閱讀 2517

問題:

最近遇到了兩個類a、b相互呼叫的情況,於是想當然的在兩個類a和b的標頭檔案中 #include 了所需的標頭檔案,當然結果編譯報錯了。為什麼呢,a需要b,b需要a,形成了迴圈,違反了程式的確定性原則。**如下圖所示:

如這樣相互包含的問題,可以使用前置宣告來解決。即:在標頭檔案中宣告該類,在實現檔案中包含該類。如下圖所示:

解析:

為什麼這樣使用前置宣告,即在aaa.h中宣告class bbb; 在bbb.h中宣告class aaa; 且成員變數寫為所宣告類的指標變數, 便不會產生相互包含的錯誤呢?

原因在於:class bbb;這種方式僅僅是一種符號宣告,告訴編譯器存在bbb這個類,不會去確定bbb這個類的所佔資源(記憶體)大小和這個類的實現。

上圖中可以看到在aaa.h中定義的是bbb的指標變數或引用變數,而不是普通的bbb變數,這是因為定義指標變數或引用變數,編譯器只需給該變數分配4位元組(32位程式)記憶體,而不用管bbb物件具體需要占用多少記憶體,也不去確定該類的建構函式是如何實現的,這些事情是在建立該物件(即aaa.cpp中:b = new bbb;)時才會去確定;

但是若定義普通的bbb變數:bbb b; 的話,編譯器需要知道b變數占用了多大記憶體,建構函式如何實現,然後計算需要為aaa類分配記憶體大小,這樣只是宣告class bbb;就不行了,否則會報錯:"使用了未定義的類bbb」,解決辦法是#include"bbb.h",又回到了開始的問題。

同理,bbb.h中關於aaa的宣告及變數定義也是如此。

優點:

使用前置變數,即:在標頭檔案中宣告該類,在實現檔案中包含該類。有其一定的優勢,以aaa類為例:

(1)bbb修改後重新編譯的話,因為是前置宣告,所以不需要重新編譯aaa.h;

(2)定義的成員變數為指標變數或引用變數,記憶體固定增加了4(32位程式),減少了aaa類的記憶體占用

大小,這體現在stl的容器裡包含是類的物件還是指標的時候特別有用。

附錄:

這裡附上成員變數宣告為"引用變數"時的用法**:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

#pragma once

classbbb;

classaaa

;

#include "aaa.h"

aaa::aaa(bbb &x) : b(x)

aaa::~aaa(void)

#pragma once

classaaa;

classbbb

;

#include "bbb.h"

#include "aaa.h"

bbb::bbb()

bbb::~bbb(void)

voidbbb::newaaa()

#include

intmain()

C 前置宣告

特點 被宣告的類不用重新編譯,節省編譯時間 比如a包含乙個指向b的指標,b包含a的乙個例項,這種情況下,使用前置宣告。易錯的點 class date class task1 因為分配器為d分配記憶體的時候,必須要知道 d的大小 主要應用場景是兩個標頭檔案相互包含的場景,建議僅將前置宣告用於解決迴圈引...

C 前置宣告

一般的前置函式宣告 見過最多的前置函式宣告,基本格式 如下 1 include 2 using namespace std 34 void fun char ch,int pvalue,double dvalue 56 void main 714 15void fun char ch,int pva...

C 編譯,前置宣告

class a class b 存在類巢狀的問題,編譯無法通過。採用前置宣告解決 class b class a class b 以上 還是錯誤的,因為在編譯期間對於類的定義需要知道其成員變數型別的大小。將a.b改為指標,因為對於特定的平台指標大小事固定的。如下是編譯四個階段的過錯。其中編譯階段不會...