2012-10-18 50 views
1

我有一個程序除了main.cpp和一個常量的頭兩個外部文件。所以共有四個文件。它們包含以下代碼:範圍在多文件程序

的main.cpp

#include <iostream> 
using namespace std; 

int ext1_func(); 
int ext2_func(); 

int main() 
{ 
    int i; 
    i = ext1_func(); 
    cout << i << endl; 

    i = ext2_func(); 
    cout << i << endl; 

    return 0; 
} 

ext1.cpp

#include "const.h" 
int asd1=1; 

int ext1_func() 
{ 
    return temp_int; 

} 

ext2.cpp

#include "const.h" 
int asd2 = 2; 

int ext2_func() 
{ 
    return temp_int; 
} 

const.h

#ifndef CONST_H 
#define CONST_H 

const int temp_int=1; 

#endif 

我期望如下:

1)在ext1.cpp聲明的任何變量應該已知到ext1.cpp內的功能,同樣也ext2.cpp。因此,「ext2_func」只能被稱爲「ext1_func」和「asd2」。

2)在「exp1.cpp」和「ext2.cpp」必須能夠看到所有的值定義「const.h」

我相信我的代碼編寫並附加滿足這些功能要求,但我想問問我是否正確地做了?有沒有比我建議的更容易的方式來獲得所需的行爲?

在此先感謝。

Niles。

+0

最大的問題'變量在其源文件之外是可見的(在各種答案中討論__),並且(2)沒有頭部聲明用於強制使用函數的代碼('main.cpp')之間的一致性的函數和定義函數的代碼('extN.cpp')。當然,C++有類型安全的鏈接(不像C,我主要工作)。但是,一般來說,最好不要在源文件中編寫extern聲明 - 應該有一個聲明用於強制執行一致性的函數的頭文件。 –

回答

2

在編譯單元級別中,您在「全局」範圍聲明的符號全部鏈接到全局變量空間。

避免這種情況的舊方法是聲明它們是靜態的。新的方法是把它們放到一個匿名的命名空間中。它們也可以在那裏聲明爲靜態的。

ext1.cpp

namespace { 
    /*static*/ int asd1=1; 
} 

標題中的常數是確定的,常量聲明這樣有特殊的地位,實際上是編譯器可以在代碼替代的價值。理想情況下,您至少應該將它們包裝在(命名)名稱空間中,以避免污染全局名稱空間。修改該值(使用const_cast)將是未定義的行爲。

如果它是非常量並且你真的想要一個全局的(通常不是一個好主意),你需要在頭文件中使用extern關鍵字,然後在一個編譯單元中創建它的實例。

+0

關於「標題中的常量可以,[...]」,謝謝你。我擔心用這種方式定義全局常量是一種糟糕的編程風格,現在我只是保持原樣。 – BillyJean

+0

全局常量沒問題,但理想情況下,您應該將它們放入(命名)名稱空間中,以免「污染」全局名稱空間。 – CashCow

1

您應該將ext1.cppext2.cpp中的變量定義爲靜態,以防止它們被其他文件看到。但是,這是構建事物的一種非常糟糕的方式。你應該把你的代碼分成不同的類。詳情請參閱this

+1

我一般不同意你「你應該把你的代碼分成不同的類」。也許應該有類和對象,但C++通常不支持「每件事都必須在類中」的範例。 – CashCow

+0

-1指向高度抽象的維基百科頁面關於OOP「的詳細信息」。另外,C++沒有理由不支持匿名命名空間這類的東西,而且當前的程序太小而無法保證OO設計。 –

2

相反重複中的main.cpp ext1_func()ext2_func()原型的,我會爲每個功能定義一個標題文件,並添加函數原型有:

// ext1.h 
#ifndef EXT1_H_INCLUDED 
#define EXT1_H_INCLUDED 

int ext1_func(); 

#endif // EXT1_H_INCLUDED 


// ext2.h 
#ifndef EXT2_H_INCLUDED 
#define EXT2_H_INCLUDED 

int ext2_func(); 

#endif // EXT2_H_INCLUDED 

在主。CPP:

#include "ext1.h" 
#include "ext2.h" 

在ext1.cpp和ext2.cpp,使用匿名命名空間地方只對源文件中的變量:

// ext1.cpp 
#include "const.h" 
#include "ext1.h" 

namespace { 

int asd1=1; 

} // anonymous namespace 


int ext1_func() 
{ 
    return temp_int; 
} 

類似的ext_2.cpp。

您可能還想在頭文件中使用便捷的#pragma once,而不是#ifndef/#define包含防護。

+0

在「const.cpp」中添加定義的好處是什麼,而不是我在「const.h」中完成的方法? – BillyJean

+2

@ niles_1710373:有關在標題中定義常量的討論,請參閱AndreyT的[answer](http://stackoverflow.com/questions/2328671/constant-variables-not-working-in-header)。 –

+0

謝謝! – BillyJean

1

當你想使局部變量翻譯單元(.cpp文件),你把它們放到一個匿名的命名空間是這樣的:

namespace 
{ 
    int local_variable = 1; 
} 

另類,你也可以做到這一點舊的C方式:

static int local_variable = 1; 

另外,您不應該在頭文件中定義變量,因爲它將在包含此頭文件的每個.cpp模塊中進行復制。你應該在const.h宣佈其外部是這樣的:

extern int external_variable; 

然後在相應的const.cpp文件定義它是這樣的:有顯示的是:(1)`ASDN代碼

int external_variable = 1; 
+0

謝謝!但是可以在「const.h」中定義一個常量變量嗎?它會在每個模塊中重複嗎? – BillyJean

+0

@ niles_1710373,對於'const int'和其他整數類型就沒關係。 – detunized