为什么这种类型的函数原型设计会抛出错误?

时间:2017-05-10 06:17:10

标签: c++

这是我的代码

#include<iostream>
//#include<cmath>
double sqrt(double);

int main()
{
    using namespace std;

    cout << sqrt(16) << endl;
    cin.get();

    return 0;
}

我只是在探索c ++,据说[C ++ Primer,Lippman]这种形式的函数原型应该正常工作。 如果我替换double sqrt(double);我的代码有效 使用注释行#include<cmath>

但是为什么另一种方法会抛出这个错误:

    $ g++ so_c++1_FntnPrototype.cpp -lm
    /tmp/cc45Ec4F.o: In function `main':
    so_c++1_FntnPrototype.cpp:(.text+0x22): undefined reference to `sqrt(double)'
    collect2: error: ld returned 1 exit status

2 个答案:

答案 0 :(得分:1)

保留库函数的名称。 C ++ 14 [extern.names] / 3:

  

使用外部链接声明的标准C库中的每个名称都保留给实现,以便在名称空间extern "C"和全局名称空间中用作std链接的名称。

     

使用外部链接声明的标准C库中的每个函数签名都保留给   实现用作具有extern“C”和extern“C ++”链接的函数签名,或者作为全局命名空间中命名空间范围的名称。

保留给实现意味着如果您尝试声明名称,则它是未定义的行为:

  

如果程序在保留它的上下文中声明或定义名称,除了本条款明确允许的名称外,其行为是未定义的。

Undefined behaviour意味着任何事情都可能发生;在这种情况下,包括无法编译的代码。

答案 1 :(得分:0)

问题是数学库(-lm)中的函数具有C链接。如果您修改sqrt原型以指示它应该具有C链接,那么您的程序链接正常:

#include<iostream>

extern "C" double sqrt(double);

int main()
{
    using namespace std;

    cout << sqrt(16) << endl;
    cin.get();

    return 0;
}

(顺便说一下。这就是使用头文件的原因 - 所以你不必记住这些细节)