LNK2005 `已經在 xxx.obj 中定義` 通常是因為**函式/變數定義放在標頭檔(.h)**,且該標頭檔被多個 `.cpp` 包含,導致每個編譯單元都產生一份定義,連結時衝突。
標頭檔 `TimeAndDate.h` 內含 **完整的類別方法定義**(非 inline、非模板),例如:
inline void data_X::setX(int x) { ... } // inline 正確
void Time::display() { ... } // 非 inline、非 static → 每個 .cpp 都會產生一份
inline void Time::display() { ... } // 加上 inline,編譯器會在每個調用點展開,不產生獨立符號
模板定義必須在 `.h`,編譯器實例化時處理重複。
你已使用 `#ifndef MY_H_FILE ... #endif`,這防止**同一編譯單元重複包含**,但**無法防止跨編譯單元重複定義**。
// TimeAndDate.h
#pragma once // 現代替代 include guard
#include
#include
class data_X { ... }; // 僅宣告
class Hour : public data_X { ... };
// ...
class Time {
public:
Time(int, int, int);
void display(); // 僅宣告
private:
Hour hour;
Minute minute;
Second second;
};
// TimeAndDate.cpp
#include "TimeAndDate.h"
Time::Time(int h, int m, int s) : hour(h), minute(m), second(s) {}
void Time::display() {
std::cout << std::setfill('0') << std::setw(2) << hour.getData() << ":"
<< minute.getData() << ":" << second.getData() << std::endl;
}
// main.cpp
#include "TimeAndDate.h"
int main() {
Time t(20, 16, 13);
t.display();
}
刪除 `Debug`/`Release`、`*.obj`、`*.pch` 等中間檔,或在 IDE 執行「清除方案」後重建,確保無舊物件檔殘留。
核心原則:**標頭檔只放宣告、內聯函式、模板;實作放 .cpp**,即可徹底避免 LNK2005。