c++tricks——命名空间

using directiveusing declaration

// using directive

int fun1(int i) {

    using namespace std;

    int vector = 7; // a poorly named variable, but it is legal.

    // vector a; // error. std::vector is hidden

    return vector * i;

}

 

// using declaration

int fun2(int i) {

    using std::vector;

    // int vector = 12; // error. redeclaration of 'vector'.

    vector a; // ok.

    return i * i;

}

int main(int argc, char *argv[]) {

    return 0;

}

fun1中的代码,<>的解释是:

One interesting aspect of using directives is that they make the names of a namespace available, but as if they were declared at *global* scope, not necessarily at the scope in which the using directive occurs. Local names will hide namespace names.

所以fun1中名字vector只有一个可见的声明,就是那个int类型的变量。std名字空间中的模板类声明被隐藏了。所以试图用vector声明一个向量会出错。

fun2中,using declaration的作用等于是在同样的位置,同样的作用域内声明了这个名字,因此试图在同一作用域内声明一个名叫vectorint类型变量的时候,会出现“重复声明”错误。

:从上面的例子可以看出,通过using directive使用命名空间容易造成命名空间污染,因此google c++规范建议禁止使用using directive方式使用namespace,改用,例子中fun1改为

int fun1(int i) {

    namespace np_std = ::std;

    int vector = 7;

np_std::vector a; 

return vector * i;

}

c++匿名命名空间与静态变量

当定义一个命名空间时,可以忽略这个命名空间的名称:

namespce {

  char c;

  int i;

  double d;

}

编译器在内部会为这个命名空间生成一个唯一的名字,而且还会为这个匿名的命名空间生成一条using指令。所以上面的代码在效果上等同于:

namespace __UNIQUE_NAME_ {

  char c;

  int i;

  double d;

}

using namespace __UNIQUE_NAME_;

在匿名命名空间中声明的名称也将被编译器转换,与编译器为这个匿名命名空间生成的唯一内部名称(__UNIQUE_NAME_)绑定在一起。还有一点很重要,就是这些名称具有internal链接属性这和声明为static的全局名称的链接属性是相同的,即名称的作用域被限制在当前文件中,无法通过在另外的文件中使用extern声明来进行链接。如果不提倡使用全局static声明一个名称拥有internal链接属性,则匿名命名空间可以作为一种更好的达到相同效果的方法。

:命名空间都是具有external 连接属性的,只是匿名的命名空间产生的__UNIQUE_NAME__在别的文件中无法得到,这个唯一的名字是不可见的。c++新的标准中提倡使用匿名命名空间,而不推荐使用static,因为static用在不同的地方,涵义不同,容易造成混淆,另外,static不能修饰class

:匿名命名空间与static功效等同。另外google c++关于匿名命名空间的规范建议不要在 .h 文件中定义命名空间。同时建议禁止定义静态储存周期非POD变量(函数作用域里的静态变量除外)。因为静态变量的构造函数、析构函数和初始化的顺序在 C++ 中是只有部分明确的,甚至随着构建变化而变化,可能导致不明确行为发生,难以发现的 bug。所以除了禁用类类型的全局变量,也不允许用函数返回值来初始化 POD 变量,除非该函数(比如 getenv() 或 getpid())不涉及任何全局变量。

实例:

//A.h

class A{

public:

  void test_space();

};

 

//A.cpp

namespace {

  int a=12;

  void testa(){

    printf("(1) %d", a);

  }

}

void A::test_space(){

  testa();

  printf("(2) %d", a);

}

 

int main(){

  A a;

  a.test_space();

}

google c++规范建议,在类型定义中,类型转换运算符和单参数构造函数都应当用 explicit 进行标记。一个例外是,拷贝和移动构造函数不应当被标记为 explicit,因为它们并不执行类型转换。对于设计目的就是用于对其他类型进行透明包装的类来说,隐式类型转换有时是必要且合适的,这时应当联系项目组长并说明特殊情况。


 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值