C/C++:多个.cpp文件包括同一个.h头文件定义方法
本文解決multiple definition of `XX'的錯誤。【出于反爬蟲的目的,你不是在http://blog.csdn.net/zhanh1218上看到的,肯定不是最新最全的。】
關于頭文件的定義中,請一定加上下面代碼(此為頭文件保護符):
<span style="font-size:14px;"><span style="font-size:12px;">#ifndef PERSON_H_ #define PERSON_H_ // 你的代碼塊 #endif /* PERSON_H_ */</span></span>
當中PERSON_H_為保護符的名字,一般建議與類名保持一致!樣例中我的類名為Person.h。
每當編譯器遇到#include時,都要去編譯相關代碼塊,可是編譯器不知道是不是已經編譯過了,假設編譯過了還去編譯,那是不是等于代碼塊寫了兩次呢?所以,須要有不反復編譯的機制,而這個機制正式以上代碼。
詳細實現為:#ifdef當且僅當變量已定義時為真,#ifndef當且僅當變量沒有定義時為真。一旦檢測結果為真,則運行興許操作直至遇到#endif。
也就是說:假設首次include "Person.h",PERSON_H_是未定義,此時,編譯器會define這個保護符,并運行代碼塊的編譯!直到遇到#endif。下次遇到這個保護符,就不會運行代碼塊的編譯了。這種機制保證了不會反復編譯。
實際使用中,我發現,單個cpp文件里多次include 同一個.h頭文件或者頭文件里多次include某個頭文件,不會有問題。可是,多個cpp文件都include 同一個.h頭文件時,這樣會出問題。問題是類外定義的非static及非inline函數還是會報multiple
definition of `XX'的錯誤。【也就是說:#define的作用域僅僅是單個.cpp,而不是全局全部的.cpp文件】
終于解決方法是:僅僅在頭文件定義類的申明和類的主體定義(也就是{}內的內容),在一個同名的.cpp文件中定義類外函數的實現!問題完美解決。所以,就算是大神寫的書,書上也不全然是對的,或者表述的所有都清楚。
那么為什么頭文件能夠定義成下面形式呢?而不是僅僅申明,不定義類體呢?
<span style="font-size:14px;"><span style="font-size:12px;">class A
{
// 類定義
};</span></span>
類的定義,僅僅是告訴編譯器,類的數據格式是怎樣的,實例話后對象該占多大空間。類的定義也不產生目標代碼。因此它和普通變量的聲明唯一的差別是不能在同一編譯單元內出現多次。
還有一個原因就是,類能夠在多個.cpp文件中重定義,變量卻不行,除非用extern或者staic修飾的變量。
至于普通變量:同意static型的變量的定義;同意extern申明(不能定義!);直接申明比如int
a; 是不行的,也是多次又一次定義。
extern表明該變量在別的地方已經定義過了,在這里要使用那個變量;static 表示靜態的變量,分配內存的時候,存儲在靜態區,不存儲在棧上面。【一篇不錯的Blog:點擊打開鏈接】
以下是代碼演示樣例,此實例部分為C++ Primer練習題。【反爬蟲,第二天更新代碼!】
/*********************************************************************
* file_name: vector_test.cpp
*
* Created on: 2014年6月28日 下午3:34:23
* Author: The_Third_Wave, Blog: http://blog.csdn.net/zhanh1218
* Email: zhanh121823@sina.com
* Last modified: 2014年6月28日 下午3:34:23
*********************************************************************/
#include <iostream>
#include <vector>
#include <string>
#include "Headers/Person.h"
extern int k;
int main()
{
std::vector<Person> per = {{"The_Third_Wave", 100, "Blog: http://blog.csdn.net/zhanh1218"}}; // 類初始化+vector初始化,所以{{}, {}}必須的
for (auto &p: per)
{
print(std::cout, p);
}
}
/********************************************************************* * file_name: ddqdq.cpp * * Created on: 2014年6月28日 下午10:28:42 * Author: The_Third_Wave, Blog: http://blog.csdn.net/zhanh1218 * Email: zhanh121823@sina.com * Last modified: 2014年6月28日 下午10:28:42 *********************************************************************/ #include <iostream> #include <vector> #include "Headers/Person.h" extern int k;
/*********************************************************************
* file_name: Person.h
*
* Created on: 2014年6月28日 下午11:47:08
* Author: The_Third_Wave, Blog: http://blog.csdn.net/zhanh1218
* Email: zhanh121823@sina.com
* Last modified: 2014年6月28日 下午11:47:08
*********************************************************************/
#ifndef PERSON_H_
#define PERSON_H_
/*****************************BEGIN***********************************/
#include <iostream>
#include <string>
using namespace std;
extern int a;
class Person
{
friend istream &read(istream &is, Person &item);
friend ostream &print(ostream &os, const Person &item);
public:
Person() = default;
Person(const string &n, unsigned int a, string add):
name(n), age(a), address(add) { }
Person(istream &);
string Name() const {return name;}
unsigned int Age() const {return age;}
string Address() const {return address;}
private:
string name = "";
unsigned int age = 1;
string address = "";
};
inline
Person::Person(istream &is)
{
read(is, *this);
}
/******************************END************************************/
#endif /* PERSON_H_ */
/*********************************************************************
* file_name: Person.cpp
*
* Created on: 2014年6月28日 下午10:55:32
* Author: The_Third_Wave, Blog: http://blog.csdn.net/zhanh1218
* Email: zhanh121823@sina.com
* Last modified: 2014年6月28日 下午10:55:32
*********************************************************************/
#include <iostream>
#include <string>
#include "Person.h"
using namespace std;
istream &read(istream &is, Person &item)
{
is >> item.name >> item.age >> item.address;
return is;
}
ostream &print(ostream &os, const Person &item)
{
os << item.name << " " << item.age << " " << item.address << endl;
return os;
}
還有不懂的請留言。
本文由@The_Third_Wave(Blog地址:http://blog.csdn.net/zhanh1218)原創。還有未涉及的,會不定期更新,有錯誤請指正。
假設你看到這篇博文時發現不完整,那是我為防止爬蟲先公布一半的原因,請看原作者Blog。
假設這篇博文對您有幫助,為了好的網絡環境,不建議轉載,建議收藏!假設您一定要轉載,請帶上后綴和本文地址。
總結
以上是生活随笔為你收集整理的C/C++:多个.cpp文件包括同一个.h头文件定义方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql -a 参数_mysql参数及
- 下一篇: linux树莓派mysql_树莓派4B(