关于C++变量的作用域域的问题

C++中的作用域解析
作者: 发布时间: 14:05:19 来源:
名字空间域  名字空间主要用于解决名字冲突的问题,在名字空间出现之前,库的作者通常通过附加给库中的类型,全局变量和函数予特定的前缀来防止名字冲突的问题,例如dbus库的Error类型和Error初始化函数被命名为:  DBusError  dbus_init_error  有了名字空间后,我们就可以通过附加名字空间的名字来构成名字的限定名(Qualified Name)来解决名字冲突的问题。  当然更主要的是我们可以通过名字空间别名,使用声明(特定的名字)和使用指示(全部名字)来达成即能有效防止冲突,又能在已确定的上下文中更方便的访问名字的作用。  跟Java的包机制不同,名字空间是纯逻辑上的,它不具备对文件组织上任何的物理约束,一个名字空间可以跨越多个编译单元(常见的方式,一个库一个名字空间),但也可以一个编译单元包含多个名字空间(比较少见,通常是用来通过嵌套的子名字空间来防止一些函数重载上的意外发生)。(Java中的包,编译单元,类型域的包含关系更加明确,容易理解和使用,一个包必然包含一个或多个编译单元,一个编译单元也必然包括一个或多个类型,而且只能有一个是包可见的――公共类)  有的意见认为,名字空间引起的问题比它解决的要多,比如连接时名字解析的问题,特别是不同编译器编译出来的程序片段(静态库,导入库,Object文件)如何能够正确的连接。名字空间也使得重载的决议规则变的更复杂。所以像有些著名的库仍然坚持使用前缀的方式,比如QT。  名字空间出现后,以前的全局域就变成了名字空间的一个特例――全局名字空间。没有放置在某个名字空间的类型,具有编译单元外部链接的非成员函数和变量就缺省属于全局名字空间。  编译单元域  编译单元域是个比较特殊的域,它通常跟代码的物理组织方式有关。一个编译单元中非成员变量和函数的名字可以有外部链接,从而使得链接器可以用来解决跨编译单元的名字引用的问题(跨编译单元的变量的名字引用通常被视为是邪恶的东西)。但是也可以没有外部链接,从而防止一些无意中产生的副作用(错误的引用了不是预想中的名字)。  没有外部链接的名字处于编译单元域,这个可以通过附加static修饰符来达成。例如:  static double static_d = 3.0;  examda提示: 也可以放置在一个特殊的名字空间里,这个名字空间叫做匿名名字空间,每个编译单元都可以有一个匿名名字空间,不同编译单元之间的匿名名字空间不会相互影响,处于匿名名字空间的名字只能被该编译单元所访问。例如:  namespace  {  double intern_d = 2.0;  }  namespace foo  {  static double static_d = 3.0;  Foo::Foo(void)  {  intern_d = 3.0;  }  Foo::~Foo(void)  {  }  }  像上面的非成员变量intern_d就是处于编译单元foo(foo.cpp)的匿名名字空间中。如果在头文件中试图导出这个变量,例如:  extern double intern_d;  实际上你会得到一个“ambiguous symbol”的编译错误(在VC 2008中)。  类型域  用户使用struct和class定义一个自定义类型,也同时构成了一个类型域,处于类型域里面的变量和函数被称为成员变量和成员函数,它们可以是静态的(属于类型),也可以是非静态的(属于实例)。静态的成员变量和成员函数与非成员变量和函数类似,而类型在这里只是起到一个特殊的名字空间的作用,或者说是附加类型成员访问规则的名字空间,公共的静态成员函数如果是可见的,那也是可访问的,也就是具备外部链接。  函数域  每个函数都构成了一个函数域,函数域的概念跟变量的存储位置和生命期有关。函数的参数和在函数中声明并定义的变量被称为局部变量或者是自动变量,它们分配在堆栈上,它们随着函数的执行而生成,随着函数的退出而消亡。而静态成员变量和非成员变量则分配在静态存储区中,它们的位置是固定的,生命期从程序启动一直到程序关闭。(在自由存储区中动态分配的对象是由使用者来控制其生命周期的。)  函数里面还可以有多个局部域,比如说每个if,else,else if,for,while,do,switch,try,catch块,或者是用户自己产生的代码块(使用{}包围)。局部域的作用通常是用来进一步限制局部变量的使用范围,在某个局部域声明的局部变量,在退出该局部域时会被自动销毁。用户自己产生的代码块(局部域)多用于所谓的关键区,用来同步线程对外部状态的访问。如果函数需要写的很长,刻意的区分不同的局部域也有助于代码的可读性和防止不必要的错误。&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
标题 全文 作者
【】【】【
】【】【】
?&&&&?&&&& ?
&更多有关新闻:
选择分类:
研究生考试
在职研考试
幼儿/中小学
课程关键字:
&热门搜索:
&2008年首都高校秋季招生
&本周推荐课程
课程咨询热线:010-68841
??????????
&育路社区&&&&&&&&&&&
学员报名服务中心: 北京北三环西路32号恒润中心1806()
咨询电话:北京- 010- 传真:010- 上海-021-
育路网-中国新锐教育社区:
本站法律顾问: 邱清荣律师
北京育路互联科技有限公司版权所有 | 京ICP备号求教。。作用域问题_c++吧_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:159,072贴子:
求教。。作用域问题收藏
#include&iostream.h&
void main()
int a=1,b=2,c=3;
cout&&”a=”&&a&&’\t’&&”b=”&&b&&’\t’&&”c=”&&c&&’\t’&&
int b=4,c=5;
cout&&”a=”&&a&&’\t’&&”b=”&&b&&’\t’&&”c=”&&c&&’\t’&&
cout&&”a=”&&a&&’\t’&&”b=”&&b&&’\t’&&”c=”&&c&&’\t’&&
cout&&”a=”&&a&&’\t’&&”b=”&&b&&’\t’&&”c=”&&c&&’\t’&&
cout&&”a=”&&a&&’\t’&&”b=”&&b&&’\t’&&”c=”&&c&&’\t’&&
为什么最后a=4.。而不是a=1
因为你a =了。出了作用域访问的话编译通不过的,所以你自己再好好想想a的作用域是哪个范围。
局部变量总是大于全局变量的通俗来讲,在一个村子里村长才是王道,不是国家领导很不负责任的说不喜勿喷
登录百度帐号推荐应用
为兴趣而生,贴吧更懂你。或当前位置: >
> C++ primer(9)-命名空间、定位new运算符、存储持续性作用域和链接行、单独编译
C++ primer(9)-命名空间、定位new运算符、存储持续性作用域和链接行、单独编译
supery2009 & at
C++ primer(九)--命名空间、定位new运算符、存储持续性作用域和链接行、单独编译  一、单独编译
  与其将结构声明加入到每一个文件中,不如将其放在头文件中,然后在每一个源代码文件中包含该头文件。也可将函数原型放在头文件中。因此,可以将原来的程序分成三部分:
头文件:包含结构声明和使用这些结构的函数的原型源代码文件:包含于结构相关的函数的代码源代码文件:包含调用与结构相关的函数的代码
  &&& 请不要将函数或变量声明放到头文件中。例如,如果在头文件中包含一个函数定义,然后在其他两个文件(属于同一个程序)中包含该头文件,则同一个程序中将包含同一个函数的两个定义,除非函数是内联的,否则这将出错。头文件中经常包含的内容:
函数原型使用#define或const定义的符号常量结构声明类声明模板声明内联函数
  &&& 结构声明在头文件中可以,因为它们不创建变量,而只是在源代码文件中声明结构变量时,告诉编译器如何创建该结构变量。模板声明不是将被编译的代码,它们指示编译器如何生成与源代码的函数调用相匹配的函数定义。被声明为const的数据和内联函数由特殊的链接属性。
  二、存储持续性
关于这个话题,可以参考这篇文章。
  &&& 单定义规则适用于非内联函数。对于链接性为外部的函数来说(也就是函数没有定义为static),这意味着在多文件程序中,只能有一个文件包含该函数的定义,但是适用该函数的每个文件都应包含其函数的原型。
  &&& 内联函数不受这些规则的约束,这允许将内联函数的定义放在头文件中。
  & 1)语言链接性
  &&& 链接程序要求每个不同的函数都有不同的符号名。在C语言中,一个名称只对应一个函数,因此这很容易实现。C语言编译器可能将spiff这样的函数名翻译为_spiff。这种方法被称为C语言链接性。但在C++中,同一个名称可能对应多个函数,必须将这些函数生成不同的符号名称。将spiff(int )转换为_spiff_i,将spiff(double,double)转换为_spiff_d_d。这种为C++语言链接。对于C和C++语言链接之间的不同,解决办法
  &&& extern &C& void spiff(int); // 用C语言链接性
  三、命名空间
  &&& 一个名称空间中的名称不会与另外一个名称空间的相同名称发生冲突,同时允许程序的其他部分使用该名称空间中声明的东西。名称空间可以是全局的,也可以位于另一个名称空间中,但不能位于代码块中。在默认情况下,在名称空间中声明的名称的链接性为外部的(除非他引用了常量)
  &&& using声明使一个名称可用,而using编译指令使所有的名称都可用。using编译指令由名称空间名和它前面的关键字using namespace组成,它使名称空间中的所有名称都可用。使用using声明比使用using编译指令更安全,这是由于它只导入指定的名称。如果该名称与局部名称发生冲突,编译器将发出指示。
本问题标题:
本问题地址:
温馨提示:本问题已经关闭,不能解答。
暂无合适的专家
&&&&&&&&&&&&&&&
希赛网 版权所有 & &&&&湘教QS2-164&&增值电信业务经营许可证湘B2-&&问题点数:0&&回复次数:9&&&
关于for循环中定义变量的作用域问题.
for(int i=0;i&10;i++){}这样的i的作用域是什么呢?
搜索更多相关主题的帖子:
等 级:新手上路
帖 子:28
i只是控制循环,当此循环结束或异常退出时候i就见阎王去了!
学习如逆水行舟,不进则退!
等 级:新手上路
帖 子:494
但是在VC中,如果我这样写:int a[10],b[10];for(int i=0;i&10;i++){
a[i]=i;}for(int i=0;i&10;i++){
b[i]=i;}它会给我重复定义i的错误,为什么呢?
等 级:新手上路
帖 子:151
标准说的是i的作用域仅在for循环内,但在vc6中,i的作用域大于循环,在vc2003中就没问题,究其原因,vc6老了,许多标准都不支持
等 级:新手上路
帖 子:28
在main()中int i,给i分配的内存还没有释放,你再定义一个i,就会出错。for(int i=0;i&10;i++){
b[i]=i;} 改成for(i=0;i&10;i++){
b[i]=i;}就可以了!
学习如逆水行舟,不进则退!
等 级:贵宾
威 望:38
帖 子:1533
不是VC6。0老了是它优化太强了都给优化了
嵌入式 ARM 单片机 驱动 RT操作系统 J2ME LINUX&&Symbian C C++ 数据结构 JAVA Oracle 设计模式 软件工程 JSP
等 级:贵宾
威 望:38
帖 子:1533
不是VC6。0老了是它优化太强了都给优化了
嵌入式 ARM 单片机 驱动 RT操作系统 J2ME LINUX&&Symbian C C++ 数据结构 JAVA Oracle 设计模式 软件工程 JSP
等 级:新手上路
帖 子:151
这算是优化?那为什么vc2003不这么优化,gcc不这么优化
等 级:新手上路
帖 子:494
以下是引用song4在 17:29:45的发言:不是VC6。0老了是它优化太强了都给优化了
优化?不是吧
等 级:新手上路
帖 子:204
怎么不是,一种语言的编译器只要能支持90%这种语言就不错了,虽然在正常的for(int i)这种定义,只在for内有效,但是,在不同的编译器中是不一样的,在其他语言,如JAVA里也会出现这种情况
樹欲靜而風不止...
/seablue_xj
版权所有,并保留所有权利。
Powered by , Processed in 0.026385 second(s), 8 queries.
Copyright&, BCCN.NET, All Rights ReservedC++模板类继承中诡异的作用域问题
下面一段代码,大家可以试试,这样的问题经常被人忽略,出错还很难查:   代码: 全选
    /*   * template_scope.cpp   *   * Created on:
下午06:13:28   * Author: kwarph   * Web:
  * Mail:
  */   #include      int x = 8;   void print() {   cout && "hello" &&   }   template   class B {   public:   B() :   x(0) {   }   explicit B(const int& v) :   x(v) {   }   void print() const {   cout && "B::print()" &&   }   protected:      };   template   class A: public B {   public:   void test_scope() const {   cout && "x = " && x && // 引用全局的x,输出 x = 8   // cout && "x = " && B::x && // 必须显式调用父类的x   print(); // 调用全局的print(),输出 hello   // B::print(); // 必须显式调用父类的函数   }   };   class C {   public:   C() :   x(0) {   }   explicit C(const int& v) :   x(v) {   }   void print() const {   cout && "C::print()" &&   }   protected:      };   class D: public C {   public:   void test_scope() const {   cout && "x = " && x && // 用父类的x,输出: x = 0   print(); // 调用父类的print(),输出: C::print()   }   };   int main() {   A   a.test_scope();   D   d.test_scope();   }
您对本文章有什么意见或着疑问吗?请到您的关注和建议是我们前行的参考和动力&&
您的浏览器不支持嵌入式框架,或者当前配置为不显示嵌入式框架。

我要回帖

更多关于 c 作用域运算符 的文章

 

随机推荐