HOWTO · C++
修復 C++ 中一個函式的多重定義錯誤
本文是關於 C++ 中多函式定義錯誤的解決方法。
這篇文章是關於 C++ 中經常出現的錯誤的解決方法,即函式的多個定義。
修復 C++ 中的 multiple definitions of a function 錯誤
這種錯誤通常是在我們試圖分離函式原型和它的定義時引起的。因此,建議你將原型和定義分開放在不同的檔案中,並相應地包含該檔案。
參考下面的例子來理解這個問題。
示例程式碼(file1.cpp):
// file1.cpp
#include <iostream>
using namespace std;
class classB {
friend void f1();
public:
classB(int i = 1, int j = 2) : a(i), b(j) {
cout << "Hello from constructor\n";
}
private:
int a;
int b;
void printfun() { cout << "a=" << a << endl << "b=" << b << endl; }
};
void f1() { // ERROR HERE
cout << "f1 start" << endl;
classB tmp(3, 5);
tmp.printfun();
cout << "f1 end" << endl;
}
示例程式碼(main.cpp):
// main.cpp
#include <iostream>
#include "file1.cpp"
using namespace std;
int main() {
cout << "calling function" << endl;
f1();
cout << "exit from main" << endl;
return 0;
}
這就是在你的情況下發生的事情。由於 file1.cpp 檔案中的 #include,file1.cpp 和 main.cpp 都包含 f1() 的定義,並且連結器不知道在你的檔案中使用哪一個程式並抱怨它。
解決方案是從 main.cpp 中刪除包含 f1() 定義的 CPP 檔案,並在單獨的標頭檔案中包含 f1() 的宣告,並將其包含在 main.cpp 中。編譯器將處理 f1() 的宣告,而連結器將僅依賴 file1.cpp 中的 f1() 定義。
示例程式碼(file1.h):
// file1.h
#include <iostream>
class classB {
friend void f1();
public:
classB(int i = 1, int j = 2) : a(i), b(j) {
std::cout << "Hello from constructor\n";
}
private:
int a;
int b;
void printfun() { std::cout << "a=" << a << endl << "b=" << b << std::endl; }
};
示例程式碼(file1.cpp):
// file1.cpp
#include "file1.h"
using namespace std;
void f1() {
cout << "f1 start" << endl;
classB tmp(5, 6);
tmp.printfun();
cout << "f1 end" << endl;
}
示例程式碼(main.cpp):
// main.cpp
#include <iostream>
#include "file1.h"
using namespace std;
int main() {
cout << "calling function" << endl;
f1();
cout << "exit from main" << endl;
return 0;
}
讓我們從標頭檔案 file1.h 開始。標頭檔案包含所有內容的定義,如函式定義、任何結構或類定義或任何常量定義。
這個 .h 副檔名告訴編譯器不要編譯這個檔案。它就像一個文字檔案,任何人都可以閱讀。
這意味著標頭檔案是一個文件檔案。如果以後有程式設計師想使用某些函式,只需要檢查函式的原型,不需要詳細介紹函式定義。
最後,模板程式碼也應該在標頭檔案中。
CPP 檔案現在定義了在標頭檔案中宣告的函式。這告訴編譯器該檔案將被編譯並轉換為二進位制檔案。
你的程式碼的完整性將受到保護,未經你的許可,任何人都不能修改它。這意味著這種程式碼分離也確保了程式碼檔案的安全性。
這種技術背後的另一個原因是便攜性。例如,你編寫了一個二進位制搜尋程式碼,以後可以在許多其他程式中使用。
如果你有這些單獨的函式檔案,則可以在任何其他專案中輕鬆使用這些函式。
最後,主檔案只包含主函式,並在頂部包含標頭檔案。這個檔案只包含主函式,它只呼叫所有函式,沒有別的。