// a.h
int 大小 = 0; // 直接在頭文件定義變數
// a.cpp
#include "a.h"
void _tmain() { 大小 = 48; }
// b.cpp
#include "a.h"
void abc() { 大小 = 48; }
編譯時產生:
error LNK2005: "int 大小" (?大小@@3HA) 已經在 b.obj 中定義
error LNK1169: 找到一個或多個多重定義的符號
頭文件被多個 .cpp 包含時,int 大小 = 0; 會在每個編譯單元(Translation Unit)中產生一個**定義**。連結器發現同一個符號在多個 .obj 中都有定義,因而報錯。#pragma once 或 #ifndef 僅能防止同一編譯單元內重複包含,無法跨編譯單元解決重複定義。
// a.h
#pragma once
extern int 大小; // 告訴編譯器:這個變數在別處定義,型別為 int
// a.cpp
#include "a.h"
int 大小 = 0; // 真正分配記憶體、初始化
void _tmain() { 大小 = 48; }
// b.cpp
#include "a.h"
void abc() { 大小 = 48; } // 連結時會解析到 a.cpp 的定義
若使用 C++17,可在頭文件直接定義:
// a.h (C++17)
#pragma once
inline int 大小 = 0; // 允許在多個編譯單元出現,連結器會合併
但傳統專案建議採用 extern + 單一定義檔,相容性最佳。
const int x = 10; 在頭文件預設具有內部連結,每個 .cpp 會有獨立副本,**不會**造成 LNK2005。但若加上 extern const int x; 則需單一定義。inline 函式定義在頭文件同樣會造成多重定義錯誤。頭文件僅放 宣告,實際 定義 放在單一 .cpp。使用 extern 關鍵字明確區分,即可徹底解決 LNK2005/LNK1169。