初學 C++ 時,將函數模板分散在頭文件與 .cpp 文件中編寫,往往會遇到「找不到標識符」或「未定義的引用」等編譯/鏈接錯誤。本文針對一個典型案例——max 函數模板——詳細說明正確的寫法與常見誤區。
用戶提供的三張截圖顯示:
max.h 中使用 #ifndef MAX_H 防止重複包含,但將模板定義被註釋掉了;max.cpp 試圖單獨編譯模板定義;main.cpp 包含頭文件並調用 max,編譯器報錯「找不到標識符 max」。函數模板的定義必須對編譯器可見。當編譯器在 main.cpp 看到 max(a, b) 時,需要知道具體如何為 int、double 等類型實例化模板。若定義藏在 max.cpp,編譯 main.cpp 時看不到,自然無法生成實例化代碼。
// max.h
#ifndef MAX_H
#define MAX_H
template <typename T>
T max(T a, T b) {
return (a > b) ? a : b;
}
#endif // MAX_H
main.cpp 只需 #include "max.h" 即可直接調用,無需額外的 .cpp 文件。
若確實想把定義放在 .cpp,必須在該 .cpp 尾部顯式實例化常用類型:
// max.cpp
#include "max.h"
template <typename T>
T max(T a, T b) { return (a > b) ? a : b; }
// 顯式實例化
template int max<int>(int, int);
template double max<double>(double, double);
但這會限制模板只能用於已實例化的類型,失去泛型優勢,**不推薦常規使用**。
extern:模板不需要也不應該用 extern,它不是普通函數。#ifndef/#define/#endif 或 #pragma once 確保頭文件只被包含一次。inline,無需手動加關鍵字。函數模板的**聲明與定義統統放在頭文件**是最簡單、最標準、最不易出錯的做法。避免將定義拆分到 .cpp,除非你清楚顯式實例化的限制並有特定優化需求。