使用命名空间与使用命名空间闭包的范围

Scope of using namespace versus using namespace closure

我试图理解为什么在使用命名空间与显式声明命名空间封闭时我的函数存在歧义。

Book.h头文件:

#ifndef MYBOOK_BOOK_H
#define MYBOOK_BOOK_H 

namespace mybook
{
    void showTitle();
    void showTableOfContents();
}

#endif

我的实现文件导致歧义错误: Book.cpp

#include "Book.h"
#include <iostream>
#include <cctype>
#include <cstring>

using namespace std;
using namespace mybook;

void showTitle() {
    cout << "The Happy Penguin" << endl;
    cout << "By John Smith" << endl;
}

void showTableOfContents() {
     cout << "Chapter 1" << endl;
     cout << "Chapter 2" << endl;
}

我的实现文件没有歧义错误: Book.cpp

#include "Book.h"
#include <iostream>
#include <cctype>
#include <cstring>

using namespace std;

namespace mybook {

   void showTitle() {
       cout << "The Happy Penguin" << endl;
       cout << "By John Smith" << endl;
   }

   void showTableOfContents() {
        cout << "Chapter 1" << endl;
        cout << "Chapter 2" << endl;
   }
}

我认为 Book.cpp 的第一个场景应该可行,因为通过在开头声明 using namespace mybook 这意味着我现在要实现我在头文件中定义的函数。但是我得到了 "error 'showTitle': ambiguous call to overload function could be 'void showTitle(void) or void mybook::showTitle(void)'" 的错误,我的其他函数 showTableOfContents 也是如此。为什么在第一种情况下使用命名空间 mybook 不起作用?

I would think that the first scenario of Book.cpp should work because by declaring using namespace mybook at the beginning it is saying that I am now going to implement the functions I defined in the header file.

这就是你不正确的地方。 using namespace mybook; 表示您正在使用 mybook 中的名称,而不是说您是 defining/adding 中 mybook 的名称。要在 mybook 中定义名称,您需要打开命名空间并将定义放入其中,就像您在第二个示例中所做的那样。

这些定义

using namespace std;
using namespace mybook;

void showTitle() {
    cout << "The Happy Penguin" << endl;
    cout << "By John Smith" << endl;
}

void showTableOfContents() {
     cout << "Chapter 1" << endl;
     cout << "Chapter 2" << endl;
}

在全局命名空间中声明两个函数。

现在您在全局命名空间和命名空间 mybook 中有四个函数,它们具有相同的声明并且由于包含 using 指令 ​​

using namespace mybook;

非限定名称查找找到所有四个函数。结果,编译器报告了歧义。

如果你想定义在命名空间 mybook 中声明的函数,那么你必须写

using namespace std;
using namespace mybook;

void mybook::showTitle() {
    cout << "The Happy Penguin" << endl;
    cout << "By John Smith" << endl;
}

void mybook::showTableOfContents() {
     cout << "Chapter 1" << endl;
     cout << "Chapter 2" << endl;
}

那就是您需要使用限定名称。

来自 C++ 17 标准(10.3.1.2 命名空间成员定义)

2 Members of a named namespace can also be defined outside that namespace by explicit qualification (6.4.3.2) of the name being defined, provided that the entity being defined was already declared in the namespace and the definition appears after the point of declaration in a namespace that encloses the declaration’s namespace.

和(7.3.4 使用指令)

3 A using-directive does not add any members to the declarative region in which it appears

请注意,由于名称查找不合格导致歧义。

如果您使用限定名称查找,那么编译器会找到在全局命名空间(在这种情况下程序会成功执行)或在命名空间 mybook(在这种情况下编译器或链接器会报告函数未定义的错误。

这是一个演示程序。

#include <iostream>

namespace mybook
{
    void f1();
    void f2();
}

using namespace mybook;

void f1() { std::cout << "::f1();\n"; }
void f2() { std::cout << "::f2();\n"; }

int main() 
{
    ::f1();
    ::f2();

    return 0;
}

它的输出是

::f1();
::f2();

如果你会写

mybook::f1();
mybook::f2();

那么会出现函数未定义的错误