为什么在C ++命名空间周围使用extern“C”

时间:2011-10-10 07:47:27

标签: c++ c gcc

几天前,我遇到了这段C ++代码,虽然我无法粘贴代码本身,但我可以用一些示例代码重新创建问题。 首先,文件命名为namespace.h:

#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:写这段代码的人早就不见了。

3 个答案:

答案 0 :(得分:14)

extern "C"指令有两个效果,它会在可能的情况下禁用重整并使用C调用约定。在这种特殊情况下,因为中间存在命名空间,所以不能禁用名称修改,因此可以添加它以强制执行特定的调用约定。

代码实际上是错误的,因为声明不会强制extern "C",但定义会强制执行,这是不正确的。考虑一下,如果编译器只是遵循如图所示的指令,调用者将使用C ++命名和调用约定,而函数将使用C变量,如果两者不同,结果将是未定义的行为。

答案 1 :(得分:6)

似乎试图生成没有C ++名称修改的变量。这是使用extern "C"的一部分。

较新的编译器显然意识到它确实不起作用。

答案 2 :(得分:2)

如果你想从一个用另一种语言编写的模块(C,FORTRAN或其他)调用一段C ++代码,你想要关闭C ++名称修改。

修改 真正奇怪的是,他们是在定义上做到的,而不是在宣言上。这是一个奇迹,它曾编译