2011-10-10 88 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变体,如果两者不同,结果将是未定义的行为。

相关问题