#include <iostream>
using namespace std;
void A() { cout << "函數A\n"; }
void B() { cout << "函數B\n"; }
int main() { A(); B(); return 0; }
編譯通過、執行正常,誤以為「函數定義在前就不需要宣告」。
void A() {
cout << "函數A\n";
B(); // 呼叫 B,但 B 尚未被編譯器「看見」
}
void B() {
cout << "函數B\n";
A(); // 呼叫 A
}
int main() { A(); B(); return 0; }
編譯錯誤:error C3861: 'B': 找不到識別項 (或同類訊息)。
原因:編譯器由上而下單遍掃描,遇到 A() 內呼叫 B() 時,B 尚未宣告/定義。
#include <iostream>
using namespace std;
// 前置宣告
void A();
void B();
void A() {
cout << "函數A\n";
B();
}
void B() {
cout << "函數B\n";
A();
}
int main() { A(); B(); return 0; }
編譯通過,但執行時進入無限遞迴 (A→B→A→B...),導致堆疊溢位崩潰。
| 概念 | 說明 |
|---|---|
| 定義 | 提供函數實作本體,同時隱含宣告 (若前無宣告)。 |
| 宣告 | 僅告知編譯器函數簽名 (名稱、回傳型別、參數),無函數體。 |
| 單遍編譯 | C/C++ 編譯器單向掃描,使用前必須已宣告或定義。 |
| 相互遞迴 | 兩函數直接/間接互呼,無終止條件 → 無限循環 → StackOverflow。 |
.h,定義於 .cpp,透過 #include 管理依賴。「函數定義在 main 前就不用宣告」是**危險的誤區**。一旦出現相互呼叫、多檔案專案、庫開發等場景,**缺少前置宣告必導致編譯失敗**。養成「先宣告、後定義、標頭檔管理」習慣,並警惕相互遞迴帶來的運行時崩潰風險。