4

我正在使用带有 Zsh 5.0.2、Vim 7.3 和 GCC 4.8.0 的 GNU/Linux 发行版来学习 C++。

由于重新定义了函数,以下代码将无法编译foo

#include <iostream>

int foo()
{
    return 0;
}

int foo()
{
    return 0;
}

int main()
{
    foo();
    return 0;
}

尝试编译它:

» g++ -g -pedantic -std=c++11 -Wall -Wextra -Weffc++ foo.cpp -o foo
fail.cpp: In function ‘int foo()’:
fail.cpp:8:5: error: redefinition of ‘int foo()’
 int foo()
     ^
fail.cpp:3:5: error: ‘int foo()’ previously defined here
 int foo()
     ^

但是,我注意到 GCC(g++具体来说是 )会自动包含<time.h>,而无需我明确指示它这样做。在一个程序中,我写了 where std::time()is used 但我忘记了#include <ctime>并使用std::前缀 this 导致time()from<time.h>被使用,而不是相应的函数 from <ctime>。我很好奇 - 当两者都包含时将使用哪个 time() ?据我所知,两者都具有该名称的功能(并且它们都以相似或相同的方式工作),请参阅:

cppreference.com: time.h time()

cppreference.com: ctime time()

考虑以下代码:

#include <ctime>
#include <time.h>
#include <iostream>

int function1()
{
    using namespace std;
    cout << "function4: " << time(NULL) << endl;
    return 0;
}

int function2()
{
    using std::time;
    std::cout << "function3: " << time(NULL) << std::endl;
    return 0;
}

int function3()
{
    std::cout << "function2: " << std::time(NULL) << std::endl;
    return 0;
}

int function4()
{
    std::cout << "function1: " << time(NULL) << std::endl;
    return 0;
}

int main()
{
    function1();
    function2();
    function3();
    function4();
    return 0;
}

它可能并不完美,但我希望我的观点得到传达。<time.h>在这里,为了清楚起见,我明确包括在内。前三个以我知道的方式声明std要使用。第四个函数只是调用time()- 在我看来,这似乎可以调用<time.h><ctime>变体中的任何一个。

问题1:为什么this(function4)不会因为歧义而导致错误或警告?

问题 2:使用哪种变体,是什么决定了其中一个优先于另一个?

问题 3:有没有办法,比如说,在运行或编译过程中输出完整的函数名称,以查看使用了什么库?

4

2 回答 2

10

如果你往里面看<ctime>,你会发现以下内容:

#include <time.h>
namespace std
{
   using ::time;
}

这意味着即使您包含<ctime>,它也会调用 in 中的一个<time.h>这是指向实际标题的链接

于 2013-05-27T09:57:03.880 回答
3

请注意,不推荐在 C++ 中使用 C 头文件;并且不能保证 C++ 头文件将定义转储到全局命名空间以及std. 任何答案都将针对您的实施。

为什么这个(function4)不会由于歧义而导致错误或警告?

有两个原因:

  • 您可以随意声明函数。在这个实现中,大多数 C 函数只在头文件中声明,并在预编译库中定义。
  • 标头具有包含保护,因此即使它们定义了函数,也可以安全地多次包含它们。

使用哪种变体,是什么决定了一种优先于另一种?

在全局命名空间中,它将是两个头文件中声明的版本;两者都声明相同的功能。通常,未指定 C++ 头文件是否也声明了该函数以及名称空间中的std函数;在您的实施中,确实如此。

有没有办法在运行或编译过程中完整地输出函数名称以查看使用了什么库?

也许; 但是没有意义,因为无论哪个标头声明它,它都是同一个函数。

于 2013-05-27T10:32:38.513 回答