Подтвердить что ты не робот

Зачем использовать extern "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

Может кто-то пролить некоторый свет на то, что должен был сделать старый код на С++, может ли это быть взломом или обходным путем, чтобы обойти старую проблему, о которой я больше не знаю. Ох, кстати, метод внутри extern "C" вызывается кодом С++, а не кодом C, который я изначально подозревал. FYI, это устаревший код сейчас, возможно, был написан в период 2001/2002 года.


Спасибо, ребята. Я пошел вперед и избавился от экстерна "С" без какого-либо значительного воздействия. @Bjorn Pollex: Парень, который написал этот код, давно ушел.

4b9b3361

Ответ 1

Директива extern "C" имеет два эффекта: она отключает манипулирование, когда это возможно, и использует соглашение о вызове C. В этом конкретном случае, поскольку между ними существует пространство имен, нельзя изменить имя mangling, поэтому его можно было бы добавить для принудительного использования определенного соглашения о вызове.

Код на самом деле ошибочен тем, что объявление не заставляет extern "C", но это определение неверно. Учтите, что если компилятор просто выполнил директиву, как показано, вызывающий будет использовать соглашения об именах и вызовах С++, в то время как функция будет использовать вариант C, если они отличаются от результата, будет undefined.

Ответ 2

Похоже на попытку сгенерировать переменные без изменения имени С++. Эта часть использования extern "C".

Новый компилятор, очевидно, понимает, что он действительно не работает.

Ответ 3

Если у вас есть кусок кода на С++, который вы хотите вызывать из модуля, написанного на другом языке (C, FORTRAN или что-то еще), вы хотите отключить управление именем С++.

Edit: Действительно странно то, что они сделали это по определению, но не по декларации. Интересно, что он когда-либо компилировался