Что использование означает в C++?

Как:

using ::size_t; using ::fpos_t; using ::FILE;

На самом деле это - вопрос, вдохновленный комментарием под этим вопросом:

Когда.h не нужный для включения заголовочного файла?

5
задан Community 23 May 2017 в 12:07
поделиться

5 ответов

Это называется с использованием объявления . На самом деле есть два способа использовать с помощью ключевого слова . Существует третья особая форма объявлений using внутри определений классов, , но здесь я сосредоточусь на общем объявлении using. (см. Ниже).

  • using объявление
  • using директива

Они имеют два совершенно разных эффекта. Объявление using объявляет имя как псевдоним для другого объявления или набора объявлений (если вы должны были назвать набор перегруженных функций). Имя объявлено в текущей области . То есть вы также можете использовать его внутри блоков

int main() {
  using std::swap;
  // ...
}

Это весьма полезно, если вы очень часто используете имя локально и не хотите использовать его префикс во всех случаях, а также это полезно при реализации свопа с использованием поиска, зависящего от аргументов. идиома.

Директива using именует пространство имен и не объявляет никаких имен. Вместо этого он изменит поиск имен, чтобы найти имена, которые на самом деле не объявлены там, где они думают. Для неквалифицированного поиска имени он находит имена, объявленные во включающем пространстве имен, которое включает как директиву using, так и целевое пространство имен. Будут найдены все имена, объявленные в целевых пространствах имен:

int cout;
int main() {
  using namespace std;
  // cout << 1; ambiguous!
}

Здесь cout будет считаться объявленным дважды в глобальном пространстве имен и вызывает двусмысленность ( :: включает как main , так и std ).В квалифицированном поиске имен он построит транзитивное замыкание пространства имен со всеми пространствами имен, указанными в директивах using.

using namespace foo;

int main() {
  ::c++; 
}

c ищется не только в глобальном пространстве имен, но также в пространстве имен foo и в пространствах имен, которые foo имеют директивы using для и так далее. Если, однако, глобальное пространство имен будет содержать прямое объявление (включая объявление using), это объявление скроет объявления, найденные косвенно с помощью директив using:

using namespace foo;
int c;

int main() {
  ::c++; // not ambiguous!
}

Объявления using могут появляться во многих местах, в том числе внутри определений классов . Его значение аналогично его значению в других местах с важным ограничением: он объявляет имя как псевдоним для одного или нескольких объявлений, но эти объявления должны быть членами базового класса. Это очень полезно для того, чтобы сделать имена видимыми в производном классе, которые в противном случае были бы скрыты тем же именем, объявленным там

struct base {
  void f();
};

struct derived : base {
  using base::f; // name "f" declared in derived
  void f(int); // overloads the using declaration
};

. Теперь вы можете вызвать d.f () . Если бы не было объявления using, то поиск по имени обнаружил бы только одно объявление f в производном и остановил поиск, не углубляясь в область видимости базового класса:

derived d;
d.f(); // invalid without the using declaration
d.f(0); // valid with or without the using declaration

// explicitly starting lookup in base: valid with or without the using declaration
d.base::f();

Это также позволяет измените доступность членов базового класса, хотя вам следует использовать это с осторожностью :)

На практике я счел полезным сделать виртуальную функцию-член снова видимой:

struct base {
  virtual void f();
  virtual void f(int);
};

struct derived : base {
  // using base::f; would solve it
  virtual void f() { ... }
};

Упс - сейчас df (0); недействителен, поскольку поиск по имени находит только нулевой параметр f ! Директива using решит эту проблему.Обратите внимание, что если вы создаете псевдоним для объявления функции, имеющей те же типы параметров и константность, что и явное объявление (например, f () в этом случае), то явное объявление все равно скроет то, что объявление using является псевдоним для - так что обе функции f () не будут конфликтовать в этом случае.

Альтернативой для решения этой проблемы является использование идиомы невиртуального интерфейса .

struct base {
  void f() { do_f(); }
  void f(int) { do_f(0); }

private:
  virtual void do_f();
  virtual void do_f(int);
};

struct derived : base {
private:
  virtual void do_f() { ... }
};

struct derived1 : derived {
private:
  virtual void do_f(int) { ... }
};

Теперь оба df (0) и df () действительны независимо от какой объект вы это называете.

6
ответ дан 18 December 2019 в 08:27
поделиться

К сожалению, вы видите неясный пример.

using ::_Filet;

Как отмечали другие, объявление using делает имя из указанного пространства имен доступным в текущем пространстве имен. Похоже, что в этом файле нет открытых пространств имен, поэтому можно предположить, что текущее пространство имен является глобальным пространством имен, а также :: без ничего, прежде чем оно обращается к глобальному пространству имен. Итак, здесь мы, кажется, перемещаем имя из глобального пространства имен в глобальное пространство имен. Что с этим случилось?

Ответ заключается в использовании макроса:

_STD_BEGIN

Это определено как пространство имен std {. Итак, что делают объявления using , так это заставляют эти имена появляться в пространстве имен std , где в противном случае они были бы только в глобальном пространстве имен.

7
ответ дан 18 December 2019 в 08:27
поделиться

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

0
ответ дан 18 December 2019 в 08:27
поделиться

Ключевое слово using позволяет переносить имена из пространства имен в текущее пространство имен. Если вы хотите использовать имя внутри пространства имен, не вводя их в текущее пространство имен, вам придется использовать формат :: , как в следующее:


std::cout << "Hello World";

Если cout переносится в текущее пространство имен, вы можете использовать его, как показано ниже:


cout << "Hello World";

Ключевое слово using может использоваться следующими способами:

  • В качестве директивы using ( using namespace ; ):

using namespace std;

Это переносит все имена внутри пространства имен std в текущее пространство имен.

  • В качестве объявления using ( using :: ; ):

using std::cout;

Это вводит только имя std :: cout в текущее пространство имен.

3
ответ дан 18 December 2019 в 08:27
поделиться

с использованием извлекают символ из его пространства имен в текущее пространство имен. Предположим следующий код:

namespace foo {
  // Assume you want to use std::string, you can either do
  std::string bar;
  // or
  using std::string;
  string bar;
}

Как видите, вы можете квалифицировать символ, используя его пространство имен (первая строка кода), или второй способ. Для символов, которые вы используете довольно часто, втягивание их в пространство имен имеет тенденцию сделать код немного более читаемым, но если у вас есть конфликт (скажем, foo содержит собственный класс string что является плохой практикой, но может случиться), квалификация его соответствующим пространством имен позволит вам разрешить конфликт.

Пространство имен :: является особым случаем, поскольку оно относится к глобальному пространству имен; в этом конкретном случае функции, о которых вы говорите, являются функциями C, а C не знает о пространствах имен C ++, поэтому они попадают в глобальное пространство имен.

Пространства имен в C ++ - очень мощный механизм, позволяющий избежать конфликтов именования символов, и я настоятельно рекомендую любому программисту на C ++ использовать их.

3
ответ дан 18 December 2019 в 08:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: