3.1 Data Member的绑定

文章开始提出了一段示例代码,并讨论了返回哪个x的问题。然后

a)   给出了我们普遍认为正确的回答,并肯定了这个想法;

b)   提醒大家,这在以前的编译器实现中,并非正确。

在早期的实现中,首先绑定的是“全局变量x”。因为该class中的x的声明尚未可见。由此导致的就是“防御性编程风格”。总结起来,具体做法有两种。

c)   将所有的data member的声明提前;

d)   将内联函数的实现移至class的声明之外。

对于第一点,我们容易理解。因为变量的声明中,较晚的声明总是可以覆盖之前的。我想说下自己对于第二点的理解。

书中将此称为“member rewriting rule”。基本意义是,内联函数的实体,在整个class未被声明完全时,是不会被evaluate的(书中将evaluated翻译为评估求值,我个人觉得不是很恰当,我也没有想出什么更好的翻译,还是用英文表意更准确一点;还有后文的resolve,翻译为“决议”也不是很通顺,觉得“解析”更好)。也即是说,内联函数内的数据成员绑定也是在要class声明之后进行的。这个意义被C++Standard提炼为“member scope resolution rules”(成员作用域解析规则)。这是书里的说法。在程序中的效果是,如果内联函数在类声明后立即展开的话,它就会被evaluate。

当然上述规则也有失效的时候,比如,成员函数的参数列表。他们遵循的规则是“第一次遇到时,被适当的决议完成”。之后作者说,“extern和nested type names之间的非直觉绑定还是会发生”。目测这句话的意思是,此时会将“nested type names”解析为extern类型。这可以用书中的实例代码来引证。

在length的定义出现之前,它被使用了两次。结果是length被认为是extern类型,符合上述分析。而之后,length的声明出现时,前述解析会被否定。原文提到,“C++ Standard把稍早的绑定标示为非法”。此句意义不甚明确。标示为非法是什么意思?编译不通过,还是编译通过,但是增加了编译的开销(因为先认为length是一种类型,但是后来的声明使得原来的判定是错误的,而要重新解析)。对于这种情况,作者建议使用防御性编程风格,这也就是说建议,将data member的声明提前到使用之前。从这一点看,是不是可以认为C语言的编程方式更为科学?

3.1 Data Member的绑定

时间: 2024-11-07 17:24:28

3.1 Data Member的绑定的相关文章

C++对象模型——Data Member的绑定(第三章)

3.1    Data Member的绑定 (The Binding of a Data Member) 考虑下面这段代码: // 某个foo.h头文件,从某处含入 extern float x; // 程序员的Point3d.h文件 class Point3d { public: Point3d(float, float, float); // 问题:被传回和被设定的x是哪一个x? float X() const { return x; } void X(float new_x) const

指向 Data Member 的指针及相关的效率影响

指向 data member 的指针是一个颇有用处的语言特性, 特别是如果你需要详细调查 class members 的底层布局的话.这个调查可以帮助你决定 vptr 是放在尾端还是起始处. 另一个用途是可以用来决定 clas 中 access sections 的次序.考察以下代码, 其中有一个 virtual function, 一个 static data member, 以及三个坐标值: class Point3d { public: virtual ~Point3d(); //...

Effective C# 学习笔记(原则一:始终能的使用属性(property),而不是可直接访问的Data Member)

原则一:始终能的使用属性(property),而不是可直接访问的Data Member    Always use properties instead of accessible data members. 为什么要使用属性: 1.Net的data binding只支持Property,而不支持public data member的访问 Data binding的目的就是把一个object的Property绑定到一个用户界面的control上,web control或者windows form

C++对象模型——"继承"与Data Member(第三章) .

3.4 "继承"与Data Member 在C++继承模型中,一个derived class object所表现出来的东西,是其自己的members加上其base class members的总和.至于derived class members和base class members的排列次序并未在C++ Standard中强制指定:理论上编译器可以自由安排.在大部分编译器上,base class members总是先出现,但属于 virtual base class的除外. 了解这种继

继承与 Data Member(2)

加上多态的情况如果我要处理一个坐标点, 而不在意这是一个 Point2d 或 Point3d 实例, 那么就需要在继承关系中提供一个 virtual function 接口: class Point2d { public: Point2d(float x = 0.0, float y = 0.0) :_x(x), _y(y){}; //x 和 y 的存取函数与前一个博客中相同 //由于对不同维度的点, 这些函数操作固定不变, 所以不必设为 virtual virtual float Z()(fl

Data 语意学---Data member的存取效率

<深度探索C++对象模型> 对于data member来说,有两种情况 static data member数据 每一个static data member只有一个实体,存放在程序的data segment之中,无论以何种方式,无论类的继承关系如何复杂,存取路径都是非常直接 Nonstatic data members 直接存放在一个class object之中,是属于一个对象的,是需要一个叫做偏移量的值来索引的. 尤其是虚拟继承,虚拟继承将为"经由base class subobj

C++对象模型——Data Member的存取(第三章)

3.3    Data Member的存取 已知下面这段代码: Point3d origin; origin.x = 0.0; x的存取成本是什么? 答案视x和Point3d如何声明而定,x可能是个 static member,也可能是个nonstatic member.Point3d可能是个独立(非派生)的 class,也可能从另一个单一的base class 派生而来;虽然可能性,但它甚至可能是从多重继承或虚拟继承而来.下面数节将依次检验每一种可能性. 先看这样一个问题,如果有两个定义,or

Data Member 的存取

考察以下代码: Point3d origin; origin.x = 0.0; 此例中 x 的存取成本是什么? 答案则是视 x 和 Pointd 而定(别打脸, 我知道这是废话). 具体的呢? 因为 x 可能是个 static member, 也可能是个 nonstiatic member; Point3d 可能是个独立的 class, 也可能是另一个 单一的class 派生而来:甚至可能是从多重继承或虚拟继承而来(请不要小看其他人的代码中的可能性, 你都很有可能不知道 C++ 还能这么写, 有

Data Member 的布局

考察以下代码: class Point3d { public: //... private: float _x; static List<Point3d*> *freeList; float _y; static const int chunkSize = 250; float _z; }; 其中, nonstatic data members 在 class object 中的排列顺序和其被声明的顺序是一致的, 但是任何介入的 static data members 都不会被放进布局之中.s