喜欢 :
using ::size_t; using ::fpos_t; using ::FILE;
Run Code Online (Sandbox Code Playgroud)
事实上,这个问题受到了这个问题的评论的启发:
不幸的是,你看的例子很模糊.
using ::_Filet;
Run Code Online (Sandbox Code Playgroud)
正如其他人所指出的那样,using声明从当前命名空间中可用的指定命名空间中创建一个名称.在该文件中似乎没有打开命名空间,因此您假设当前命名空间是全局命名空间,并且::在它处理全局命名空间之前没有任何内容.所以这里我们似乎正在将名称从全局名称空间移动到全局名称空间中.那是怎么回事?
答案是使用宏:
_STD_BEGIN
Run Code Online (Sandbox Code Playgroud)
这被定义为namespace std {.所以using声明正在做的是使这些名称出现在std命名空间中,否则它们只会出现在全局命名空间中.
这是使用声明调用的.实际上有两种方法可以使用using关键字.在类定义中使用声明的第三种特殊形式,但我将重点关注此处的一般使用声明.(见下文).
它们有两种非常不同的效果.using 声明声明一个名称是另一个声明或一组声明的别名(如果你要命名一组重载函数).该名称在当前范围内声明.也就是说,你也可以在块内使用它
int main() {
using std::swap;
// ...
}
Run Code Online (Sandbox Code Playgroud)
如果您经常在本地使用名称并且不希望在所有用途中使用前缀,这非常有用,并且它在使用与段相关的查找习惯用法实现交换时也很有用.
using 指令命名命名空间,不声明任何名称.相反,它将修改名称查找以查找未真正声明它们所在位置的名称.对于非限定名称查找,它查找在封闭命名空间中声明的名称,该名称空间包含using指令和目标命名空间.将找到在目标名称空间中声明的所有名称:
int cout;
int main() {
using namespace std;
// cout << 1; ambiguous!
}
Run Code Online (Sandbox Code Playgroud)
在这里,cout将被认为是在全局命名空间中声明两次,并导致歧义(::包含两者main和std).在限定的 namelookup中,它将使用using指令中命名的所有命名空间构建命名空间的传递闭包.
using namespace foo;
int main() {
::c++;
}
Run Code Online (Sandbox Code Playgroud)
c不仅在全局命名空间中查找,而且在命名空间foo和foo具有using指令等的命名空间中查找.但是,如果全局命名空间包含直接声明(包括using声明),则该声明将隐藏使用指令间接发现的声明:
using namespace foo;
int c;
int main() {
::c++; // not ambiguous!
}
Run Code Online (Sandbox Code Playgroud)
使用声明可以出现在很多地方,包括内部类定义.它的含义类似于其他有重要限制的含义:它声明一个名称是一个或多个声明的别名,但声明必须是基类的成员.这对于在派生类中显示名称非常有用,否则这些名称将由在此处声明的相同名称隐藏
struct base {
void f();
};
struct derived : base {
using base::f; // name "f" declared in derived
void f(int); // overloads the using declaration
};
Run Code Online (Sandbox Code Playgroud)
现在你可以打电话了d.f().如果没有使用声明,那么名称查找只会找到一个fin derived和stop查询的声明,而不是深入研究基类范围:
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();
Run Code Online (Sandbox Code Playgroud)
它还允许更改基类成员的可访问性,尽管你应该谨慎使用:)
在实践中,我发现它有助于使虚拟成员函数重新可见:
struct base {
virtual void f();
virtual void f(int);
};
struct derived : base {
// using base::f; would solve it
virtual void f() { ... }
};
Run Code Online (Sandbox Code Playgroud)
糟糕 - 现在d.f(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) { ... }
};
Run Code Online (Sandbox Code Playgroud)
现在,无论是d.f(0)和d.f()是有效的,你叫什么对象时,它不管.
| 归档时间: |
|
| 查看次数: |
2923 次 |
| 最近记录: |