2013-12-19 174 views
3

內的頭部聲明函數指針我有一個包含以下一個簡單包頭:一個命名空間

// system.h 
#pragma once 
namespace System 
{ 
    void Initialize(void); 
    int (*Main)(int& argc, char** argv); 
    void Shutdown(void); 
} 

在「system.cpp」,初始化()被限定爲使得所述函數指針主(INT, char **)被設置爲另一個主函數,由預處理器確定將定義的任何系統將被編譯(Windows,現在)。

在程序的main.cpp中,它調用上述三種功能...

所以,當這編譯,我得到一個鏈接錯誤(system.cpp)抱怨系統:主(INT, char **)已經在main.cpp中定義。這是怎麼回事?

// system.cpp 
#include "..\system.h" 
#ifdef _WINDOWS 
#include "windows.h" 
#else 
#define SYSTEM_UNKNOWN 1 
#endif 
void System::Initialize(void) 
{ 
#ifdef WINDOWS 
    System::Main = &Windows::Main; 
#else if SYSTEM_UNKNOWN 
    System::Main = NULL; 
#endif 
} 

void System::Shutdown(void) 
{ 
    System::Main = NULL; 
} 

我加入了 '的extern' 關鍵字的頭......而仍然沒有去。

+0

試過'extern'...不行:/我得到未解決的外部符號錯誤......這很奇怪。由於它是在system.cpp中定義的! – user3120381

+0

好的!顯然我沒有初始化函數中的定義......這是不愉快的。 – user3120381

回答

3

int (*Main)(int& argc, char** argv); 

是變量Main定義。對於聲明,則需要extern

extern int (*Main)(int& argc, char** argv); 

,並在實現文件移動的定義。

你可以嘗試同樣的(具有相同效果),用簡單的例子:

int x; 

這也是一個定義。

+0

啊,C的喜悅:你可以在這裏說'extern int private_variable;'並在別人的'.c'文件中修改全局變量。 –

+0

@Joker_vD'static'關鍵字? –

+0

@Joker_vD:如果這個'private_variable'是通過外部鏈接聲明的,那麼它並不是真正的私有的。但事實確實如此,C的黑白聯動隱私模式相當粗糙:它可以是內部的(任何人都可以訪問),也可以是外部的(任何人都無法訪問)。 – AnT

2

您上面的Main不只是一個聲明。這也是一個定義。如果您將此標頭包含在多個文件中,則每個文件都將定義一個版本Main。你想聲明變量爲extern後來在一個.cpp文件中定義它:

namespace System { 
    extern int (*Main)(int&, char**); // declaration 
} 

int (*Main)(int&, char**) = ...; // definition 
0

int (*Main)(int& argc, char** argv);不應該讀你讀功能向前聲明的方式,就像其他兩個線代碼框。這一行定義了一個名爲Main的數據變量,它具有類型「指向函數返回int指針的指針」。它類似於在頭文件中表示int j;

正如其他人所說,在它前面加extern,然後有行,因爲它現在處於cpp文件,將解決你的問題。不過,我認爲了解此行爲背後的原因是有益的。

編輯:這是麪點,但有可能是沒有理由通過argc在這種情況下的參考:你不救,因爲內存的指針和int很可能是相同的尺寸或者更糟糕,並且它向讀者建議您可以在Main函數中修改argc,其方式需要在main中反映出來,我假定Main被調用,我猜我猜想不是這種情況。

1

你有一個典型的普通的多重定義錯誤,這是由於你的定義了一個變量在頭文件中有外部鏈接(然後將該頭文件包含到多個翻譯單元中) 。命名空間與它無關,並且沒有任何區別。

當你添加extern關鍵字你轉身所有這些定義非定義聲明頭。鏈接器錯誤立即變得不同。現在,而不是多重定義錯誤,你有一個缺少定義的錯誤。

在標題中添加extern關鍵字是朝正確方向邁出的一步。現在,你只需要創建一個定義了變量

int (*Main)(int& argc, char** argv); 
在一個

(且只有一個)實現文件。