c++ 中的 using 是什么意思?

发布于 2024-08-27 01:11:30 字数 243 浏览 11 评论 0原文

喜欢:

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

事实上,这是一个受到此问题下评论启发的问题:

什么时候.h不需要包含头文件?

Like :

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

In fact it's a question inspired by the comment under this question:

When is .h not needed to include a header file?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

蓝颜夕 2024-09-03 01:11:30

这称为使用声明。实际上有两种方法可以使用 using 关键字。在类定义中使用了第三种特殊形式的 using 声明,,但我将在这里重点介绍一般的 using 声明。(见下文)。

  • using 声明
  • using 指令

它们有两种截然不同的效果。 using 声明将一个名称声明为另一个声明或一组声明的别名(如果您要命名一组重载函数)。该名称在当前范围内声明。也就是说,您也可以在块内使用它。

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

如果您在本地经常使用名称并且不想在所有使用中都为其添加前缀,那么这非常有用,并且在使用依赖于参数的查找惯用法实现交换时也很有用。

using 指令命名命名空间,但不声明任何名称。相反,它会修改名称查找,以查找未在其认为的位置真正声明的名称。对于非限定名称查找,它会查找在包含 using 指令和目标命名空间的封闭命名空间中声明的名称。将找到在目标命名空间中声明的所有名称:

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

这里,cout 将被认为在全局命名空间中声明了两次,并导致歧义(:: 包含mainstd)。在限定 namelookup 中,它将使用 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
};

现在您可以调用 df() 了。如果没有 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() 都是有效的。

This is called using declaration. There are actually two ways you can use the using keyword. There is a third special form of using declarations used inside class definitions, but i'll focus on the general using declaration here. (see below).

  • using declaration
  • using directive

These have two very different effects. A using declaration declares a name to be an alias to another declaration or a set of declarations (if you were to name a set of overloaded functions). The name is declared in the current scope. That is, you can use it inside blocks too

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

This is quite useful if you use a name very often locally and you don't want to prefix it in all uses, and it's also useful in implementing the swap using argment dependent lookup idiom.

A using directive names a namespace and does not declare any names. Instead it will modify name lookup to find names that aren't really declared where it thinks they are. For unqualified name lookup, it find names declared in the enclosing namespace that encloses both the using directive and the target namespace. All names that are declared in the target namespaces will be found:

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

Here, cout will be thought as being declared twice in the global namespace, and causes an ambiguity (:: encloses both main and std). In qualified namelookup, it will build the transitive closure of a namespace with all the namespaces named in using directives.

using namespace foo;

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

c is not only looked up in the global namespace, but also in the namespace foo and in the namespaces that foo has using directives for and so on. If however the global namespace would contain a direct declaration (including a using declaration), that declaration will hide the declarations found indirectly by using directives:

using namespace foo;
int c;

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

Using declarations can appear in many places, including inside class definitions. Its meaning is similar to its meaning otherwhere with an important restriction: It declares a name to be an alias to one or more declarations, but the declarations must be members of a base class. This is very useful for making names visible in a derived class that would otherwise be hidden by the same name declared there

struct base {
  void f();
};

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

Now you can call d.f(). If there were no using declaration, then name lookup would only find one declaration of f in derived and stop lookup, not delving into the base class scope:

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();

It also allows to change the accessibility of base-class members, although you should use that sparingly :)

In practice, i found it useful for making virtual member function re-visible:

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

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

Oops - now d.f(0); is invalid because name lookup only finds the zero parameter f! The using directive would solve it. Notice that if you alias a function declaration that has the same parameter types and constness as an explicit declaration (like f() in this case), then the explicit declaration will still hide the one that the using declaration is an alias for - so both f() functions won't conflict in this case.

An alternative to solve this is using the non-virtual interface idiom

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) { ... }
};

Now, both d.f(0) and d.f() are valid no matter on what object you call it.

信仰 2024-09-03 01:11:30

不幸的是,您正在查看的示例很模糊。

using ::_Filet;

正如其他人所指出的,using 声明使指定命名空间中的名称在当前命名空间中可用。在该文件中,似乎没有打开任何命名空间,因此您会假设当前命名空间是全局命名空间,并且 :: 在寻址全局命名空间之前没有任何内容。所以这里我们似乎将一个名称从全局命名空间移动到全局命名空间中。这是怎么回事?

答案是使用宏:

_STD_BEGIN

这被定义为namespace std {。因此,using 声明所做的就是使这些名称出现在 std 命名空间中,否则它们只会出现在全局命名空间中。

Unfortunately the example you're looking at is obscure.

using ::_Filet;

As others have noted, the using declaration makes a name from the specified namespace available in the current namespace. In that file there appear to be no namespaces opened, so you'd assume the current namespace is the global namespace, and also the :: with nothing before it addresses the global namespace. So here we seem to be moving a name from the global namespace into the global namespace. What's up with that?

The answer is in the use of a macro:

_STD_BEGIN

This is defined as namespace std {. So what the using declarations are doing is making those names appear in the std namespace, where otherwise they would only be in the global namespace.

旧情别恋 2024-09-03 01:11:30

using 将符号从其命名空间拉入当前命名空间。假设有以下代码:

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++ 程序员使用它们。

using <some symbol> pull a symbol from its namespace into the current namespace. Assume the following code:

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

As you can see, you can either qualify the symbol using its namespace (first line of code) or the second way. For symbols you use quite often, pulling them into the namespace tends to make the code a little more readable but if you have a conflict (say, foo contains a string class of its own which is bad practise but might happen), qualifying it with the appropriate namespace will allow you to resolve the conflict.

The namespace :: is a special case as it refers to the global namespace; in this particular case, the functions you're referring to are C functions and C doesn't know about C++ namespaces, so they end up in the global namespace.

Namespaces in C++ are a very powerful mechanism to avoid symbol naming clashes and I'd strongly encourage any C++ programmer to use them.

枕花眠 2024-09-03 01:11:30

“using”关键字允许您将命名空间中的名称引入当前命名空间。
如果您想在命名空间内使用名称而不将其带入当前命名空间,则必须使用 :: 格式,如下所示:


std::cout << "Hello World";

如果将 cout 引入当前命名空间,那么您可以像下面这样使用它:


cout << "Hello World";

using 关键字可以通过以下方式使用:

  • 作为 using 指令 ​​(using namespace;):

using namespace std;

这会将 std 命名空间内的所有名称带入当前命名空间。

  • 作为 using 声明(using::;):

using std::cout;

这仅将 std::cout 名称引入当前命名空间。

The 'using' keyword allows you to bring names from a namespace into the current namespace.
If you would like to use a name inside a namespace without bringing them into your current namespace, you would have to use the <namespace name>::<name> format, as in the following:


std::cout << "Hello World";

If cout is brought into the current namespace, then you can use it like below:


cout << "Hello World";

The using keyword can be used the following ways:

  • As a using directive (using namespace <namespace name>;):

using namespace std;

This brings all names inside the std namespace into the current namespace.

  • As a using declaration (using <namespace>::<member name>;):

using std::cout;

This brings only the std::cout name into the current namespace.

前事休说 2024-09-03 01:11:30

using 使指定命名空间中的名称在当前命名空间中可用。

using makes a name from the specified namespace available in the current namespace.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文