Область использования пространства имен по сравнению с использованием закрытия пространства имен - PullRequest
1 голос
/ 16 января 2020

Я пытаюсь понять, почему в моих функциях возникает неоднозначность, когда я использую использование пространства имен по сравнению с явным объявлением вложения пространства имен.

Заголовочный файл Book.h:

#ifndef MYBOOK_BOOK_H
#define MYBOOK_BOOK_H 

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

#endif

My файл implmenetation, который вызывает ошибку неоднозначности: 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 должен работать, потому что, объявив в начале использование пространства имен mybook, он говорит, что теперь я собираюсь реализовать функции, которые я определил в заголовочном файле. Однако я получаю ошибки "error 'showTitle': неоднозначный вызов функции перегрузки может быть 'void showTitle (void) или void mybook :: showTitle (void)'" и таким же для моей другой функции showTableOfContents. Почему использование пространства имен mybook в первом сценарии не работает?

Ответы [ 2 ]

5 голосов
/ 16 января 2020

Я думаю, что первый сценарий Book. cpp должен работать, потому что, объявив в начале использование пространства имен mybook, он говорит, что теперь я собираюсь реализовать функции, которые я определил в заголовочном файле.

Вот где вы не правы. using namespace mybook; говорит, что вы используете имена из mybook, а не то, что вы определяете / добавляете имена к mybook. Чтобы определить имена в mybook, вам нужно открыть пространство имен и поместить в него определения, как вы это делали во втором примере.

0 голосов
/ 16 января 2020

Эти определения

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 Члены именованного пространства имен также могут быть определены вне это пространство имен с явной квалификацией (6.4.3.2) определяемого имени, при условии, что определяемый объект уже был объявлен в пространстве имен, и определение появляется после точки объявления в пространстве имен, которое охватывает пространство имен объявления.

и (7.3.4 Использование директивы)

3 Директива using не добавляет никаких элементов в декларативную область, в которой она появляется

Обратите внимание на то, что двусмысленность возникла из-за неквалифицированного поиска имени.

Если вы использовали поиск по квалифицированному имени, тогда компилятор f Обнулить функции, объявленные в глобальном пространстве имен (в этом случае программа будет выполнена успешно) или в пространстве имен 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();

, то произойдет ошибка, что функции не определено.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...