[C++] 前向聲明(forward declaration)

原文鏈接:https://www.baidu.com/link?url=o1jn8t-b_N6hH4-njODSS_JWu2mn34LfVshEKAHhAmRSWIMuElEVADB08mdodr3sP2ODsmNozXMljIfnFd2MTa&wd=&eqid=a472c62400061e58000000065d56701c

 

 

1 前向聲明只是一種“聲明”

2 爲什麼前向聲明在C++中是必要的

編譯器想要確定沒有拼寫錯誤,並且傳遞給函數的參數也是對的,因此編譯器要求在調用任何函數之前,必須首先看到該函數的聲明。簡而言之,任何變量或函數等,都是要求先聲明再使用。

3 聲明和定義之間的區別

函數聲明需要提供返回類型,調用約定,方法名,參數以及參數類型,而定義要求有代碼實現。

4 前向聲明能顯著縮短編譯鏈接時間

通過使用 #include一些含有函數聲明的頭文件, 你可以將函數聲明加到你的當前 .cpp文件或 .h文件中,然而,這會拖慢編譯時間。尤其是如果在.h文件中#include 頭文件時,這是因爲,任何#include你寫的.h文件的文件,結局是都將#include你所#include的頭文件,編譯器一下子需要編譯無窮無盡的文件,即使需要調用的實際上只有一兩個函數。 
爲了避免這種情況,你可以使用前向聲明,也就是在文件頂部給出函數聲明。對於大型項目,使用前向聲明有可能使數小時的編譯時間壓縮爲只需要幾分鐘。

5 當兩個定義互相使用對方時,打破循環。

除此之外,實現前向聲明可以打破循環。這種情況是,兩個函數試圖互相調用對方。如果出現這種情況,可以#include一個頭文件,但是那個頭文件又試圖#include你目前正在寫的文件,兩個文件互相#include, 可以使用前向聲明解決這個問題。即一個文件使用前向聲明,另一個文件使用 #include

舉例:

文件Car.h:

// File Car.h
#include "Wheel.h"  // Include Wheel's definition so it can be used in Car.
#include <vector>
class Car
{
    std::vector<Wheel> wheels;
};

但是對於頭文件 Wheel.h, 必須提供Car 的聲明,原因是因爲類Wheel含有一個指向Car的指針,但是不能在文件 Wheel.h 中包含Car.h,如果包含,將產生編譯錯誤。如果Wheel.h 包含 Car.h, Car.h 又會包含 Wheel.h, Wheel.h 又會包含Car.h, 如此將陷入不斷的循環中,所以編譯器沒有這樣做,而是引發了一個錯誤。 
解決這個問題的方法是聲明Car,不能使用包含:

// File Wheel.h
class Car;     // forward declaration
class Wheel
{
    Car* car;
};

如果類 Wheel 含有方法,這些方法需要調用Car的方法,那麼Wheel的方法可以定義在文件Wheel.cpp 中,Wheel.cpp 可以包含Car.h, 但不會導致循環。

6 另一個例子

相對簡單的例子, 兩個文件 main.cpp 和 add.cpp, 使用前向聲明,不包含頭文件,一樣可以編譯通過:

// add.cpp:
int add(int x, int y)
{
    return x + y;
}
// main.cpp:
#include <iostream>
int add(int x, int y); // 前向聲明
int main()
{
    std::cout << "The sum of 3 and 4 is " << add(3, 4) << std::endl;
    return 0;
}
  •  

[1] https://stackoverflow.com/questions/4926105/what-is-forward-declaration-in-c 
[2] https://stackoverflow.com/questions/553682/when-can-i-use-a-forward-declaration 
[3] https://stackoverflow.com/questions/4757565/what-are-forward-declarations-in-c

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章