Using c что это
Перейти к содержимому

Using c что это

  • автор:

Объявление using

Объявление using вводит имя в декларативный регион, в котором отображается объявление using.

Синтаксис

using [typename] nested-name-specifier unqualified-id ; using declarator-list ; 

Параметры

Вложенный описатель имен — последовательность имен, классов или перечислений и операторов разрешения область (::), завершаемая оператором разрешения область. Один оператор разрешения область может использоваться для представления имени из глобального пространства имен. Ключевое слово typename является необязательным и может использоваться для разрешения зависимых имен при вводе в шаблон класса из базового класса.

unqualified-id — неквалифицированное выражение идентификатора, которое может быть идентификатором, перегруженным именем оператора, определяемым пользователем литеральным оператором или именем функции преобразования, именем деструктора класса или именем шаблона и списком аргументов.

декларатор-list A разделенный запятыми список вложенных typename имен-описателейunqualified-id, за которым следует при необходимости многоточием.

Замечания

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

Пример: using объявление в поле класса

Объявление using может использоваться в определении класса.

// using_declaration1.cpp #include class B < public: void f(char) < printf_s("In B::f()\n"); >void g(char) < printf_s("In B::g()\n"); >>; class D : B < public: using B::f; // B::f(char) is now visible as D::f(char) using B::g; // B::g(char) is now visible as D::g(char) void f(int) < printf_s("In D::f()\n"); f('c'); // Invokes B::f(char) instead of recursing >void g(int) < printf_s("In D::g()\n"); g('c'); // Invokes B::g(char) instead of recursing >>; int main()
In D::f() In B::f() In B::g() 

Пример: using объявление для объявления члена

Если объявление using объявляет член, оно должно ссылаться на член базового класса.

// using_declaration2.cpp #include class B < public: void f(char) < printf_s("In B::f()\n"); >void g(char) < printf_s("In B::g()\n"); >>; class C < public: int g(); >; class D2 : public B < public: using B::f; // ok: B is a base of D2 // using C::g; // error: C isn't a base of D2 >; int main()
In B::f() 

Пример: using объявление с явной квалификацией

Участники, объявленные с помощью объявления using, можно ссылаться с помощью явной квалификации. Префикс :: указывает на глобальное пространство имен.

// using_declaration3.cpp #include void f() < printf_s("In f\n"); >namespace A < void g() < printf_s("In A::g\n"); >> namespace X < using ::f; // global f is also visible as X::f using A::g; // A's g is now visible as X::g >void h() < printf_s("In h\n"); X::f(); // calls ::f X::g(); // calls A::g >int main()
In h In f In A::g 

Пример: using синонимы объявления и псевдонимы

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

Имя, определенное объявлением using , — это псевдоним исходного имени. Оно не влияет на тип, компоновку и другие атрибуты исходного объявления.

// post_declaration_namespace_additions.cpp // compile with: /c namespace A < void f(int) <>> using A::f; // f is a synonym for A::f(int) only namespace A < void f(char) <>> void f() < f('a'); // refers to A::f(int), even though A::f(char) exists >void b() < using A::f; // refers to A::f(int) AND A::f(char) f('a'); // calls A::f(char); >

Пример: локальные объявления и using объявления

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

// functions_in_namespaces1.cpp // C2874 expected namespace B < int i; void f(int); void f(double); >void g() < int i; using B::i; // error: i declared twice void f(char); using B::f; // ok: each f is a function >

В приведенном выше примере второй оператор using B::i объявляет вторую переменную int i в функции g() . Оператор using B::f не конфликтует с функцией f(char) , поскольку имена функций, вводимых в код при помощи B::f , имеют разные типы параметров.

Пример: объявления и using объявления локальных функций

Локальное объявление функции не может иметь такое же имя и тип, что и функция, введенная в код объявлением using. Например:

// functions_in_namespaces2.cpp // C2668 expected namespace B < void f(int); void f(double); >namespace C < void f(int); void f(double); void f(char); >void h() < using B::f; // introduces B::f(int) and B::f(double) using C::f; // C::f(int), C::f(double), and C::f(char) f('h'); // calls C::f(char) f(1); // C2668 ambiguous: B::f(int) or C::f(int)? void f(int); // C2883 conflicts with B::f(int) and C::f(int) >

Пример: using объявление и наследование

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

// using_declaration_inheritance1.cpp #include struct B < virtual void f(int) < printf_s("In B::f(int)\n"); >virtual void f(char) < printf_s("In B::f(char)\n"); >void g(int) < printf_s("In B::g\n"); >void h(int); >; struct D : B < using B::f; void f(int) < // ok: D::f(int) overrides B::f(int) printf_s("In D::f(int)\n"); >using B::g; void g(char) < // ok: there is no B::g(char) printf_s("In D::g(char)\n"); >using B::h; void h(int) <> // Note: D::h(int) hides non-virtual B::h(int) >; void f(D* pd) < pd->f(1); // calls D::f(int) pd->f('a'); // calls B::f(char) pd->g(1); // calls B::g(int) pd->g('a'); // calls D::g(char) > int main()
In D::f(int) In B::f(char) In B::g In D::g(char) 

Пример: using специальные возможности объявления

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

Дополнительные сведения о специальных возможностях членов см. в разделе «Член-контроль доступа».

// using_declaration_inheritance2.cpp // C2876 expected class A < private: void f(char); public: void f(int); protected: void g(); >; class B : public A < using A::f; // C2876: A::f(char) is inaccessible public: using A::g; // B::g is a public synonym for A::g >; 

using (справочник по C#)

Источник этого содержимого можно найти на GitHub, где также можно создавать и просматривать проблемы и запросы на вытягивание. Дополнительные сведения см. в нашем руководстве для участников.

Обратная связь

Ожидается в ближайшее время: в течение 2024 года мы постепенно откажемся от GitHub Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделе https://aka.ms/ContentUserFeedback.

Отправить и просмотреть отзыв по

Дополнительные ресурсы

Значок отказа согласно Закону Калифорнии о защите конфиденциальности потребителей (CCPA)

  • Светлая
  • Темная
  • Высокая контрастность
  • Предыдущие версии
  • Блог
  • Участие в доработке
  • Конфиденциальность
  • Условия использования
  • Товарные знаки
  • © Microsoft 2024

Using c что это

При чтении и записи в предыдущих темах использовались объекты std::cout и std::cin соответственно. Причем они использовались с префиксом std:: . Этот префикс указывает, что объекты cout, cin, endl определены в пространстве имен std . А само двойное двоеточие :: представляет оператор области видимости (scope operator), который позволяет указать, в каком пространстве имен определен объект. И без префикса эти объекты по умолчанию мы использовать не можем.

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

Использование оператора using имеет следующий формат:

using пространство_имен::объект

Например, пусть у нас есть следующая программа:

#include int main() < int age; std::cout > age; std::cout

Здесь используются сразу три объекта из пространства имен std : cout , cin и endl . Перепишем программу с использованием using:

#include using std::cin; using std::cout; using std::endl; int main() < int age; cout > age; cout

Для каждого объекта из пространства std определяется свое выражение using. При этом программа будет работать также как и раньше.

Определение псевдонимов

Ключевое слово using также позволяет определять псевдонимы для типов. Это может пригодиться, когда мы работаем с типами с длинными названиями, а определение коротких псевдонимов позволит сократить код. Например:

#include using ullong = unsigned long long; int main() < ullong n ; std::cout

В данном случае для типа unsigned long long определен псевдоним ullong . Стоит отметить, что это именно определение псевдонима, а НЕ определение нового типа.

Стоит отметить, что для определения псевдонимов в С++ также может использоваться старый подход в стиле языка С с помощью оператора typedef :

#include typedef unsigned long long ullong; int main() < ullong n ; std::cout

Using c что это

В прошлой теме, где рассматривалась реализация метода Dispose, говорилось, что для его вызова можно использовать следующую конструкцию try..catch:

Test(); void Test() < Person? tom = null; try < tom = new Person("Tom"); >finally < tom?.Dispose(); >> public class Person : IDisposable < public string Name < get;>public Person(string name) => Name = name; public void Dispose() => Console.WriteLine($" has been disposed"); >

Однако синтаксис C# также предлагает синонимичную конструкцию для автоматического вызова метод Dispose — конструкцию using :

using (Person tom = new Person(«Tom»))

Конструкция using оформляет блок кода и создает объект некоторого типа, который реализует интерфейс IDisposable, в частности, его метод Dispose. При завершении блока кода у объекта вызывается метод Dispose.

Важно, что данная конструкция применяется только для типов, которые реализуют интерфейс IDisposable.

Test(); void Test() < using (Person tom = new Person("Tom")) < // переменная tom доступна только в блоке using // некоторые действия с объектом Person Console.WriteLine($"Name: "); > Console.WriteLine("Конец метода Test"); > public class Person : IDisposable < public string Name < get;>public Person(string name) => Name = name; public void Dispose() => Console.WriteLine($" has been disposed"); >
Name: Tom Tom has been disposed Конец метода Test

Здесь мы видим, что по завершении блока using у объекта Person вызывается метод Dispose. Вне блока кода using объект tom не существует.

Начиная с версии C# 8.0 мы можем задать в качестве области действия всю окружающую область видимости, например, метод:

Test(); void Test() < using Person tom = new Person("Tom"); // переменная tom доступна только в блоке using // некоторые действия с объектом Person Console.WriteLine($"Name: "); Console.WriteLine("Конец метода Test"); > public class Person : IDisposable < public string Name < get;>public Person(string name) => Name = name; public void Dispose() => Console.WriteLine($" has been disposed"); >

В данном случае using сообщает компилятору, что объявляемая переменная должна быть удалена в конце области видимости — то есть в конце метода Test. Соответственно мы получим следующий консольный вывод:

Name: Tom Конец метода Test Tom has been disposed

Освобождение множества ресурсов

Для освобождения множества ресурсов мы можем применять вложенные конструкции using. Например:

void Test() < using (Person tom = new Person("Tom")) < using (Person bob = new Person("Bob")) < Console.WriteLine($"Person1: Person2: "); >// вызов метода Dispose для объекта bob > // вызов метода Dispose для объекта tom Console.WriteLine("Конец метода Test"); >

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

Мы можем сократить это определение:

void Test() < using (Person tom = new Person("Tom")) using(Person bob = new Person("Bob")) < Console.WriteLine($"Person1: Person2: "); > // вызов метода Dispose для объектов bob и tom Console.WriteLine("Конец метода Test"); >

И, как уже было выше сказано, в C# мы можем задать в качестве области действия для объектов, создаваемых в конструкции using, весь метод:

private static void Test() < using Person tom = new Person < Name = "Tom" >; using Person bob = new Person < Name = "Bob" >; Console.WriteLine($"Person1: Person2: "); Console.WriteLine("Конец метода Test"); > // вызов метода Dispose для объектов bob и tom

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *