Google C++ Style Guide----作用域
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Google C++ Style Guide----作用域,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4300字,纯文字阅读大概需要7分钟。
内容图文
![Google C++ Style Guide----作用域](/upload/InfoBanner/zyjiaocheng/1323/e884fe31da474c969b61d130428f41ca.jpg)
二、作用域
1. 命名空间(Namespaces)
在.cc 文件中,提倡使用不具名的命名空间(unnamed namespaces,译者注:不具名的 命名空间就像不具名的类一样,似乎被介绍的很少:-()。使用具名命名空间时,其名称可基于项目或路径名称,不要使用 using 指示符。
定义:命名空间将全局作用域细分为不同的、具名的作用域,可有效防止全局作用域的命名 冲突。
优点:命名空间提供了(可嵌套)命名轴线(name axis,译者注:将命名分割在不同命名空间内),当然,类也提供了(可嵌套)的命名轴线(译者注:将命名分割在不同类的作用域内)。
结论:根据下文将要提到的策略合理使用命名空间。
1) 不具名命名空间(Unnamed Namespaces)
namespace { // .cc 文件中 // 命名空间的内容无需缩进 enum { UNUSED, EOF, ERROR }; <span style="white-space:pre"> </span>// 经常使用的符号 bool AtEof() { return pos_ == EOF; } // 使用本命名空间内的符号 EOF } // namespace
然而,与特定类关联的文件作用域声明在该类中被声明为类型、静态数据成员或静态成员函数,而不是不具名命名空间的成员。像上文展示的那样,不具名命名空间结束时用注释// namespace 标识。
不能在.h 文件中使用不具名命名空间。
2) 具名命名空间(Named Namespaces)
具名命名空间使用方式如下:
命名空间将除文件包含、全局标识的声明/定义以及类的前置声明外的整个源文件封装起来, 以同其他命名空间相区分。
// .h 文件 namespace mynamespace { // 所有声明都置于命名空间中 // 注意不要使用缩进 class MyClass { public: ... void Foo(); }; } // namespace mynamespace // .cc 文件 namespace mynamespace { // 函数定义都置于命名空间中 void MyClass::Foo() { ... } } // namespace mynamespace
通常的.cc 文件会包含更多、更复杂的细节,包括对其他命名空间中类的引用等。
#include "a.h" DEFINE_bool(someflag, false, "dummy flag"); class C; // 全局命名空间中类 C 的前置声明 namespace a { class A; } // 命名空间 a 中的类 a::A 的前置声明 namespace b { ...code for b... // b 中的代码 } // namespace b
不要声明命名空间 std 下的任何内容,包括标准库类的前置声明。声明 std 下的实体会导 致不明确的行为,如,不可移植。声明标准库下的实体,需要包含对应的头文件。
最好不要使用 using 指示符,以保证命名空间下的所有名称都可以正常使用。
// 禁止——污染命名空间 using namespace foo;
在.cc 文件、.h 文件的函数、方法或类中,可以使用 using。
// 允许:.cc 文件中 // .h 文件中,必须在函数、方法或类的内部使用 using ::foo::bar;
在.cc 文件、.h 文件的函数、方法或类中,还可以使用命名空间别名。
// 允许:.cc 文件中 // .h 文件中,必须在函数、方法或类的内部使用 namespace fbz = ::foo::bar::baz;
2. 嵌套类(Nested Class)
定义:可以在一个类中定义另一个类,嵌套类也称成员类(member class)。
class Foo { private: // Bar 是嵌套在 Foo 中的成员类 class Bar { ... }; };
优点:当嵌套(成员)类只在被嵌套类(enclosing class)中使用时很有用,将其置于被 嵌套类作用域作为被嵌套类的成员不会污染其他作用域同名类。可在被嵌套类中前置声明嵌 套类,在.cc 文件中定义嵌套类,避免在被嵌套类中包含嵌套类的定义,因为嵌套类的定义 通常只与实现相关。
缺点:只能在被嵌套类的定义中才能前置声明嵌套类。因此,任何使用 Foo::Bar*指针的 头文件必须包含整个 Foo 的声明。
结论:不要将嵌套类定义为 public,除非它们是接口的一部分,比如,某个方法使用了这 个类的一系列选项。
3. 非 成员函数(Nonmember)、静 态 成 员 函 数( Static Member)和 全 局 函 数( Global Functions)
优点:某些情况下,非成员函数和静态成员函数是非常有用的,将非成员函数置于命名空间 中可避免对全局作用域的污染。
缺 点:将非成员函数和静态成员函数作为新类的成员或许更有意义,当它们需要访问外部资 源或具有重要依赖时更是如此。
结论:
有时,不把函数限定在类的实体中是有益的,甚至需要这么做,要么作为静态成员,要么作 为非成员函数。非成员函数不应依赖于外部变量,并尽量置于某个命名空间中。相比单纯为 了封装若干不共享任何静态数据的静态成员函数而创建类,不如使用命名空间。
定义于同一编译单元的函数,被其他编译单元直接调用可能会引入不必要的耦合和连接依 赖;静态成员函数对此尤其敏感。可以考虑提取到新类中,或者将函数置于独立库的命名空 间中。
如果你确实需要定义非成员函数,又只是在.cc 文件中使用它,可使用不具名命名空间或static 关联(如 static int Foo() {...})限定其作用域。
4. 局部变量(Local Variables)
C++允许在函数的任何位置声明变量。我们提倡在尽可能小的作用域中声明变量,离第一 次使用越近越好。这使得代码易于阅读,易于定位变量的声明位置、变量类型和初始值。特 别是,应使用初始化代替声明+赋值的方式。
int i;
i = f(); // 坏——初始化和声明分离
nt j = g(); // 好——初始化时声明
注意:gcc 可正确执行 for (int i = 0; i < 10; ++i)(i 的作用域仅限 for 循环),因此其 他 for 循环中可重用 i。if 和 while 等语句中,作用域声明(scope declaration)同样是 正确的。
while (const char* p = strchr(str, ‘/‘)) str = p + 1;
注意:如果变量是一个对象,每次进入作用域都要调用其构造函数,每次退出作用域都要调 用其析构函数。
// 低效的实现
for (int i = 0; i < 1000000; ++i) {
Foo f; // 构造函数和析构函数分别调用 1000000 次!
f.DoSomething(i);
}
类似变量放到循环作用域外面声明要高效的多:
Foo f; // 构造函数和析构函数只调用 1 次
for (int i = 0; i < 1000000; ++i) { f.DoSomething(i);
}
5. 全局变量(Global Variables)
class 类型的全局变量是被禁止的,内建类型的全局变量是允许的,当然多线程代码中非常 数全局变量也是被禁止的。永远不要使用函数返回值初始化全局变量。
不幸的是,全局变量的构造函数、析构函数以及初始化操作的调用顺序只是被部分规定,每 次生成有可能会有变化,从而导致难以发现的 bugs。
因此,禁止使用 class 类型的全局变量(包括 STL 的 string, vector 等等),因为它们的 初始化顺序有可能导致构造出现问题。内建类型和由内建类型构成的没有构造函数的结构体
可以使用,如果你一定要使用 class 类型的全局变量,请使用单件模式(singleton pattern)。
对于全局的字符串常量,使用 C 风格的字符串,而不要使用 STL 的字符串:
const char kFrogSays[] = "ribbet";
虽然允许在全局作用域中使用全局变量,使用时务必三思。大多数全局变量应该是类的静态 数据成员,或者当其只在.cc 文件中使用时,将其定义到不具名命名空间中,或者使用静态 关联以限制变量的作用域。
记住,静态成员变量视作全局变量,所以,也不能是 class 类型!
译者:这一篇主要提到的是作用域的一些规则,总结一下:
1. .cc 中的不具名命名空间可避免命名冲突、限定作用域,避免直接使用 using 提示符污 染命名空间;
2. 嵌套类符合局部使用原则,只是不能在其他头文件中前置声明,尽量不要 public;
3. 尽量不用全局函数和全局变量,考虑作用域和命名空间限制,尽量单独形成编译单元;
4. 多线程中的全局变量(含静态成员变量)不要使用 class 类型(含 STL 容器),避免 不明确行为导致的 bugs。
作用域的使用,除了考虑名称污染、可读性之外,主要是为降低耦合度,提高编译、执行 效率。
举例来说,两个不同项目的全局作用域都有一个类 Foo,这样在编译或运行时造成冲突。如 果每个项目将代码置于不同命名空间中,project1::Foo 和 project2::Foo 作为不同符号 自然不会冲突。
缺点:命名空间具有迷惑性,因为它们和类一样提供了额外的(可嵌套的)命名轴线。在头 文件中使用不具名的空间容易违背 C++的唯一定义原则(One Definition Rule (ODR))。
原文:http://blog.csdn.net/qianqin_2014/article/details/51354903
内容总结
以上是互联网集市为您收集整理的Google C++ Style Guide----作用域全部内容,希望文章能够帮你解决Google C++ Style Guide----作用域所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。