2012-06-20 163 views
3

我有兩個名爲file_utils.h和file_utils.cpp的文件,其中包含由不同類使用的一些方法和變量。下面是它的外觀的例子:C++ extern關鍵字和全局變量

file_utils.h:

namespace my_namespace 
{ 
extern Foo* foo; 
extern Bar* bar; 

void my_function(Blah* blah); 
} 

file_utils.cpp

#include "file_utils.h" 

void my_namespace::my_function(Blah* blah) 
{ 
    foo = 0; // undefined reference to my_namespace::foo 
    bar = 0; // undefined reference to my_namespace::bar 
    //... 
} 

some_class.cpp

#include "file_utils.h" 

some_function() 
{ 
    my_namespace::my_function(blah); 
    this->foo = *my_namespace::foo; // will that work ok? 
} 

所以誤差在評論。如果我刪除了extern關鍵字,我得到multiple definition of my_namespace::foo錯誤。問題是什麼?從設計角度來看,這甚至是一個好主意,還是應該嘗試使用靜態成員和方法來代替類?

+5

你必須在**中定義**你的對象。cpp'文件,而'extern'只聲明**一個靜態鏈接的對象。 – akappa

回答

7

問題是,你只有宣稱爲而不是定義爲的變量。

您需要提供一個實現文件的定義:

file_utils.cpp

#include "file_utils.h" 

//definition: 
namespace my_namespace 
{ 
    Foo* foo; 
    Bar* bar; 
} 

//alternatively, to keep the same formatting you have 
//Foo* my_namespace::foo; 
//Bar* my_namespace::bar; 

void my_namespace::my_function(Blah* blah) 
{ 
    foo = 0; 
    bar = 0; 
    //... 
} 
+1

我更喜歡你評論過的風格,'Foo * my_namespace :: foo;'。這樣,弄錯變量名會導致編譯錯誤,而不是默默地聲明一個新的變量。 –

+0

@MikeSeymour:嘗試編譯「namespace ns {} char * ns :: foo;」並看看你得到了什麼。 – abarnert

0

首先,我會真的建議你澄清自己兩個區別:

  • 聲明vs定義
  • 編譯器vs鏈接器

在你的情況你會得到鏈接錯誤。未定義的引用意味着,您的代碼指向某處,但鏈接程序無法找出位置。

當您使用在您的代碼中找到的某個對象時,extern關鍵字用於抑制編譯器錯誤。在你的例子中,鏈接器試圖找到你的類的實例,但失敗。這是不常用的指針(糾正我,如果我錯了)。 因此:

utils.h

namespace mySpace{ 
    extern Foo foo; // notes that foo of type Foo will be used. 

    void myFn(); 
} 

utils.cpp

#include "utils.h" 

void mySpace::myFn(){ 
    foo.bar = 5; // changes a member of foo from globals.cpp 
} 

globals.cpp

Foo mySpace::foo; // this is the actual foo used. 

如果您想要關於some_class.cpp回答的問題,請向社區提供什麼是conversions以及您想要實現的內容。

從語義上判斷我相信它是對類conversions的成員的引用。

+0

這是一個錯字,應該是'my_namespace :: foo'。 – jaho