C++編譯與鏈接(0)


C++中有的東西需要放在可以在.h文件中定義,有的東西則必須放在.cpp文件中定義,有的東西在不同的cpp文件中的名字可以一樣,而有的則不能一樣

那么究竟哪些東西可在頭文件中定義,聲明,哪些東西又必須在.cpp中定義,聲明呢?

 

*以下所有的討論都是在全局命名空間中(即不定義自己的namespace)下進行的

 

函數

1、在.h中只能聲明函數,在.cpp中可以聲明與定義函數

如果在.h中聲明並定義一個函數,則該函數只能被#include一次,否則則會出現重定義錯誤

比如

1.h

#pragma once

void show()
{

}

a.cpp

#include "1.h"

b.cpp

#include "1.h"

error LNK2005: "void __cdecl show(void)" (?show@@YAXXZ) 已經在 a.obj 中定義 

所以要避免在頭文件中定義函數

 

2、在不同.cpp中定義的函數原型(函數返回值,函數名稱,函數參數)不能完全一樣,

比如如果有在兩個.cpp文件中均存在

void show(){};

會出現重定義錯誤

 

內聯函數

為了確保所有調用該inline函數的文件中的定義一樣,所以需要是在.h文件中定義

注意這里的inline對於編譯器來說只是建議性的,關於該內聯函數被拒絕會在下一篇文章中介紹

 

 

typedef

在不同的cpp中可以一樣

 

 

變量

1、在.h中只能聲明,在.cpp中可以聲明與定義一個變量

如果在.h中的定義一個變量,則該變量被include兩次以上時則會出現重定義錯誤

2、在不同.cpp中定義的變量的名字與類型不同一樣

 

 

 

常量

1、如果const常量是用常量表達式進行初始化的,則可以在.h中聲明與定義

2、如果const變量是用非常量表達式進行初始化的,那么該變量應該在cpp文件中定義,而在.h文件中進行聲明。

3、不同cpp中以定義名字與類型一樣的變量

 

 

 

static變量

1、在不同的cpp中可以定義名字與類型一樣的變量

2、如果在.h中定義一個static成員,則所有include該文件的文件均擁有一份獨立的該static成員,一個文件對其的修改不會影響到另一個文件

所以static變量一般是放在.cpp出現並定義.

例如

1.h

#pragma once

static int a = 5;

a.cpp

#include "1.h"
#include
<iostream>
using namespace std;

void showstatic()
{
cout
<< "In a.cpp:" << a << endl;
a
= 1;
cout
<< "In a.cpp:" << a << endl;
}

b.cpp

#include "1.h"
#include
<iostream>
using namespace std;


void showstatic();
int main()
{
showstatic();
cout
<< "In b.cpp:" << a << endl;
system(
"pause");
}

image

 

 

 

static函數

在不同的cpp中可以定義函數原型一樣的函數

 

 

 

不同的cpp中類的名字可以一樣

 

 

 

類成員與函數

在.h中定義,所有成員必須在類中聲明,在cpp中實現

非靜態的常量整形數據成員不能就地初始化(*C++11中,標准允許使用等號=或者花括號{}進行就地的非靜態成員變量初始化)

在類內部定義的成員函數將自動作為inline處理

在.h外部定義的函數需要加上inline說明

否則在被include多次時會出現重定義錯誤

1.h

#pragma once
#include
<iostream>


class A
{
public:
void show();
};
void A::show()//無inline
{
std::cout
<< "hello" << std::endl;
}

a.cpp

#include "1.h"
#include
<iostream>
using namespace std;

b.cpp

#include "1.h"
#include
<iostream>
using namespace std;

error LNK2005: "public: void __thiscall A::show(void)" (?show@A@@QAEXXZ) 已經在 a.obj 中定義   

 

 

類的const成員

在類中聲明變量為const類型的成員不可以就地初始化

const常量的初始化必須在構造函數初始化列表中初始化,而不可以在構造函數函數體內初始化(*C++11中,標准允許使用等號=或者花括號{}進行就地的非靜態成員變量初始化)

#pragma once
class A
{
public:
const int i=50;
};

error C2864: “A::i”: 只有靜態常量整型數據成員才可以在類中初始化    d:\我的資料庫\documents\visual studio 2010\projects\fasd\fasd\1.h    5    1    fasd

 

 

類的靜態的數據成員

不可以就地初始化,需要到.cpp中進行定義

(對於非常量的靜態成員變量,C++11與C++98保持了一致。需要到頭文件以外去定義它)

 

 

類的靜態的常量整形數據成員

可以就地初始化

class A
{
private:
const static int i = 5;
};

 

 

 

模板(不考慮export)

模板函數與模板類的聲明與實現必須放在一個文件中

 

 

總結

  是否可以在.h中定義 在不同.cpp中是否可以重名 特殊說明
函數 不可以,會出現重定義錯誤 不可以  
內聯函數 可以 可以 為了確保所有調用該inline函數的文件中的定義一樣,所以需要是在.h文件中定義
typedef ---------------------- 可以  
常量 可以 可以

1、常量表達式進行初始化的,則可以在.h中聲明與定義

2、非常量表達式進行初始化的,那么該變量應該在cpp文件中定義,而在.h文件中進行聲明。

變量 不可以,會出現重定義錯誤 不可以(類型與名字)  
static變量 可以 可以

在.h中定義一個static成員,則所有include該文件的文件均擁有一份獨立的該static成員,一個文件對其的修改不會影響到另一個文件

所以static變量一般是放在.cpp出現並定義.

static函數 可以 可以  

 

 

 

 

 

  是否可以在.h中定義 是否可以就地初始化 特殊說明
可以    
類數據成員 ------------------ 不可以 (*C++11中,標准允許使用等號=或者花括號{}進行就地的非靜態成員變量初始化)
類成員函數 ------------------ ----------------

在.h外部定義的函數需要加上inline說明

否則在被include多次時會出現重定義錯誤

類const數據 ------------------ 不可以

1、在類中聲明變量為const類型的成員不可以就地初始化

const常量的初始化必須在構造函數初始化列表中初始化,而不可以在構造函數函數體內初始化

2、同類數據成員中的特殊說明

類的靜態的數據成員 ------------------- 不可以

不可以就地初始化,需要到.cpp中進行定義

(對於非常量的靜態成員變量,C++11與C++98保持了一致。需要到頭文件以外去定義它)

 

類的靜態的常量整形數據成員

------------------ 可以  

 

 

 

  特殊說明
模板

模板函數與模板類的聲明與實現必須放在一個文件中

 

至於為什么會這樣,與C++的編譯和鏈接,和編譯產生的目標文件(.obj),內部鏈接,外部鏈接有關,

我會在接下來的文章中向大家介紹


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



C++編譯與鏈接(1) c++編譯與鏈接 C++編譯與鏈接(2) c++編譯鏈接不對 C++編譯與鏈接 C、C++編譯,鏈接,extern鏈接 C++編譯鏈接錯誤 C++編譯和鏈接原理 c++編譯鏈接模板 C++ 模板的編譯與鏈接
 
粤ICP备14056181号  © 2014-2021 ITdaan.com