是否可以通过extern链接重载函数?

时间:2014-10-02 12:09:19

标签: c++ function linkage

我在std::atexit声明中看到了一个奇怪的代码:

extern "C"   int atexit( void (*func)() );
extern "C++" int atexit( void (*func)() ); // ... why are there two functions?

我猜它是某种函数重载,但它似乎显然是错误的。

它是什么?为什么有必要?

2 个答案:

答案 0 :(得分:4)

您的来源问题

这是一个有点误导的cppreference。

使用不同的存储类说明符两次声明相同的函数是非法的causes a build failure。如果您查看 libstdc ++ (GCC标准库实现)的来源,您将看到only the extern "C" version is actually provided


标准对此

的看法

虽然[C++11: 18.5]列出了两个声明,就像cppreference一样,但意味着两者都可以在单个实现中使用;这意味着某个实现可能会选择声明 :也就是说,它会占用[C++11: 17.6.4.3.3/4],其中包含:

  

使用外部链接声明的标准C库中的每个函数签名都保留给实现,以用作函数签名,同时使用extern" C"和extern" C ++"联系 [..]

此外:

  

[C++11: 17.6.2.3/2]:使用外部链接声明的C标准库中的名称是extern "C"还是extern "C++"链接是实现定义的。建议实现使用extern "C++"链接来实现此目的

这条规则在这里明确说明:

  

[C++11: 7.5/5]:如果两个声明声明具有相同名称的函数,并且参数类型列表(8.3.5)是同一命名空间的成员,或者声明具有相同名称的对象是同一命名空间的成员,声明赋予这些名称不同的语言联系,该程序是不正确的;如果声明出现在不同的翻译单元中,则无需诊断。 [..]


为什么这会令人困惑

在我看来,这确实会导致标准内其他地方出现一些问题;例如:

  

[C++11: 25.5/2]:内容与标准C库标题<stdlib.h>相同,但以下情况除外:

     

[C++11: 25.5/3]:函数签名:

bsearch(const void *, const void *, size_t, size_t,
        int (*)(const void *, const void *));
     

被两个声明替换:

extern "C" void *bsearch(const void *key, const void *base,
                         size_t nmemb, size_t size,
                         int (*compar)(const void *, const void *));

extern "C++" void *bsearch(const void *key, const void *base,
                           size_t nmemb, size_t size,
                           int (*compar)(const void *, const void *));
     

两者都与原始声明具有相同的行为。

I consider that to be a language defect.

答案 1 :(得分:0)

我认为你看不到这样的代码。至少可能有类似于#if#ifdef的预处理程序指令将这两个声明分开,因为根据C ++标准

5 如果两个声明声明具有相同名称和参数类型列表(8.3.5)的函数成为同一名称空间的成员,或者声明具有相同名称的对象作为成员相同的名称空间和声明为名称提供不同的语言链接,程序格式不正确; 如果声明出现在不同的翻译单元中,则无需诊断。除了具有C ++链接的函数之外,没有链接规范的函数声明不应位于该函数的第一个链接规范之前。在看到明确的链接规范之后,可以在没有链接规范的情况下声明函数;前面声明中明确指定的链接不受此类函数声明的影响。