2011-10-10 79 views
13

幾天前,我遇到了這段C++代碼,雖然我不能粘貼代碼本身,但我可以用一些示例代碼重新創建問題。 首先,文件,namespace.h:爲什麼在C++名稱空間周圍使用extern「C」

#include <iostream> 
using namespace std; 

namespace useless{ 
    class X { 
    int m_myint; 
    static X *m_foobar; 
    X* getPrivVal(void); 
    public: 
    int getMember(void); 
    X* getStaticVal(void); 
    }; 
} 

接下來,namespace.cpp

#include "namespace.h" 

extern "C"{ 
    namespace useless{ 
    X* X::m_foobar = NULL; 
    X* X::getPrivVal(void){ 
     if(m_foobar == NULL) 
      m_foobar = new X; 
     return(m_foobar); 
    } 
    } 
} 

namespace useless { 
    int X::getMember(void){ 
     if(m_myint == 0) 
      m_myint = 1; 
     return(m_myint); 
    } 
    X* X::getStaticVal(void){ 
     return(getPrivVal()); 
    } 
} 

using namespace useless; 

int main(void){ 
    X y; 
    cout << "The int value is " << y.getMember() << endl; 
    cout << "The value of the static member is " << y.getStaticVal() << endl; 
    return(0); 
} 

此代碼編譯,當我用G ++ 3.4.3聯的細,但給人當我用下面的錯誤g ++ 4.x,我已經嘗試了GCC 4.6.1以及GCC 4.2.1。已經在Linux和Mac上嘗試過,結果相同。

這是錯誤(SUSE):

g++ -o namespace namespace.cpp 
namespace.h:8:15: error: previous declaration of useless::X* 
    useless::X::m_foobar with C++ linkage 
namespace.cpp:5:11: error: conflicts with new declaration with C linkage 

可有人請闡明什麼遺留的C++代碼是希望做一些輕,這會不會是一個黑客或替代方法來解決老問題我不再知道。哦,順便說一下,extern "C"中的方法是由C++代碼調用的,而不是我最初懷疑的C代碼。僅供參考,這是現在的遺留代碼,可能是在2001/2002期間編寫的。


謝謝你們。我已經走了,擺脫了外部「C」沒有重大影響。 @Bjorn Pollex:寫這段代碼的人早已不在了。

+6

如果此代碼是版本控制的,請檢查歷史記錄以查找是誰寫的,然後用棍子打他們,直到他們悔改自己的罪。 –

回答

6

看起來像試圖生成的變量與C++名稱mangling。這是使用extern "C"的一部分。

較新的編譯器顯然意識到它確實不起作用。

2

如果您有一段C++代碼想從另一種語言(C,FORTRAN或其他語言)編寫的模塊中調用,您希望關閉C++名稱修改。

編輯: 真奇怪的是,他們做的是定義而不是聲明。這是一個奇蹟,它曾經編譯過

+3

當您談論C++ - 類和名稱空間之類的獨有功能時,關閉名稱綁定是沒有意義的。 –

14

extern "C"指令有兩個效果,它儘可能地禁用了mangling,並使用C調用約定。在這種特殊情況下,由於名稱空間介於兩者之間,因此無法禁用名稱修改,因此可能會添加名稱來強制執行特定的調用約定。

該代碼實際上是錯誤的,該聲明不強制extern "C"但定義,這是不正確的。考慮一下,如果編譯器只是按照所示的指令執行,調用者將使用C++命名和調用約定,而函數將使用C變體,如果兩者不同,結果將是未定義的行爲。

相關問題