Как выбрать одну перегрузку функции с помощью namespace :: function в C ++? - PullRequest
22 голосов
/ 16 августа 2011

рассмотрим следующий код C ++.

namespace A {
    void f() { // first function
    }

    void f(int) { // second function
    }
}
...
using A::f; // introduces both functions

Можно ли ввести только одну функцию?

Ответы [ 7 ]

18 голосов
/ 16 августа 2011

Это поведение четко определено в Стандарте .

C++03 7.3.3 The using declaration:

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

8 голосов
/ 16 августа 2011
Ключевое слово

using приведет все имена в текущую область.Так что с этим текущим кодом это невозможно.

Однако вы можете частично ввести имена в файл следующим образом:

namespace A {
  void f();  // declaration
}
using A::f;
// now only `A::f()` is visible in the subsequent code
// technically `A::f(int)` is not yet visible (thus unusable)

// introduce the other function later on
namespace A {
  void f(int);
}

Демо .

Редактировать : лучше - это поместить A::f(int) во вложенный namesapce и ввести псевдоним (для простоты использования).

namespace A {
  void f();
  namespace Internal {
    void f(int);
  }
}
using A::f;
namespace A_ = A::Internal;

Теперь другая функция также может использоваться как A_::f(int).

3 голосов
/ 16 августа 2011

Не так, как я знаю. Вы можете написать функцию-обертку, если это проблема.

void f(int i) { A::f(i); }
2 голосов
/ 16 октября 2014

Я приведу еще несколько примеров в дополнение к остальным ответам.

Многие книги по программированию на C ++ часто раскрывают все пространство имен STD, добавляя следующую строку где-то в начале исходного файла:

using namespace std;

Раскрытие полного пространства имен на самом деле является плохой практикой в ​​реальной жизни из-за различных конфликтов, которые могут возникнуть в какой-то момент, особенно когда код предоставляется многими разработчиками, работающими над одной и той же задачей.Такой стиль программирования также противоречит одному из основных правил объектно-ориентированного программирования - избегайте демонстрации большего, чем это необходимо, путем инкапсуляции ваших данных.Вот почему, например, классы имеют открытых и закрытых членов, получателей и установщиков и так далее.Пространства имен - это просто еще один способ группировки информации.Экспонирование всего пространства имен std противоречит этому правилу, особенно если вы хотите использовать, скажем, только std :: cout , std :: cin и станд :: епсИ .Вы можете легко применить , используя к определенным функциям, что позволяет вам более точно управлять и с большей вероятностью избежать конфликтов имен в нескольких пространствах имен, которые вы можете использовать в определенный момент:

using std::cout;
using std::cin;
using std::endl;

Это позволяет вам вызывать cout , cin и endl в вашем коде без префикса пространства имен.Если в какой-то момент возникает конфликт имен, гораздо, гораздо проще взглянуть на набор , используя директивы , вместо того, чтобы интересоваться, откуда во всем пространстве имен, которое вы выявили, возникает ошибка.

Люди также используют директиву using для одной функции / переменной, если существует цепочка пространств имен или имя пространства имен слишком длинное.Если у вас есть что-то вроде

namespace my_really_long_and_pointless_namespace_that_does_nothing_at_all {
    void foo() { ... }
}

или

namespace1 {
    namespace2 {
        ...
            namepaceN {
                void foo() { ... }
            }
    }
}

, то будет неприятно, когда вам придется писать все это каждый раз, когда вы хотите вызвать foo () метод.Написав

using my_really_long_and_pointless_namespace_that_does_nothing_at_all::foo;

и, соответственно,

using namespace1::namespace2:: ... ::namespaceN::foo;

, вы избавите свои пальцы от работы.

1 голос
/ 16 августа 2011

Попробуйте сделать это:

namespace A { 
    void f() { // first function 
    } }

using A::f; // introduces only above function

namespace A { 

    void f(int) { // second function 
    } 
} 
0 голосов
/ 07 февраля 2017

C ++ не имеет механизма для импорта одной конкретной перегрузки функции из пространства имен.

В качестве обходного пути вы можете обернуть вызов функции в локальную функцию:

static inline void f(int i) { A::f(i); }

Ключевое слово static очень важно -

  1. Снижает риск загрязнения глобального пространства имен до текущей единицы компиляции
  2. Это позволяет делать это в нескольких блоках компиляции (и, следовательно, может быть помещено в заголовочный файл)
  3. Это позволяет компилятору исключить дополнительный вызов функции (в сгенерированном коде не будет разницы между вызовами f() и A::f())
  4. Если f никогда не вызывается, дополнительный код генерироваться не будет
0 голосов
/ 16 августа 2011

Можно обернуть их в другую область:

namespace B { // Wrap the first function
    void f() { A::f(); }
}

namespace C { // Wrap the second function
    void f(int i) { A::f(i); }
}

int main(int argc, char *argv[])
{
    {
        using B::f; // Make the first function available
        f();
    } // Make the first function unavailable

    {
        using C::f; // Make the second function available
        f(0);
    } // Make the second function unavailable

    return 0;
}

Но я не думаю, что вы можете сделать это с помощью одной using декларации.

...