3.1 data member 绑定
extern float _x;
class Point3d
{
public:
Point3d(float, float, float);
float X() const {return _x;} // return 的是哪个 _x
void X(float x) const { _x = x;}
private:
float _x, _y, _z;
};
早期的编译器两种防御性程序设计风格:
class Point3d
{
//在 class 声明的起头处放置所有的 data member
float x, y, z;
public:
float X() const {return _x;}
//...
};
class Point3d
{
//把所有的 inlines 移到 class 之外
Point3d();
float X() const;
void X(float) const;
};
inline float Point3d:: X() const { return _x; }
这个古老的规则(member rewriting rule):inline 函数实体在整个 class 声明未被看见之前, 是不会被评估求值的。这种风格至今存在, 但从C++ 2.0 之后已经没有必要。
C++ standard 将 重写规则(rewriting rule) 提炼为 成员范围解析规则(member scope resolution rules):如果 inline函数在class声明之后立刻被定义的话,那么就还是对其评估的。
extern int _x;
class Point3d
{
public:
//对于函数本身的分析将延迟,直到 class 声明的右大括号出现才开始
float X() const { return _x; }
private:
float _x;
};
//事实上, 分析从这才刚开始
对成员函数本体的分析,直到整个class的声明都出现才开始。因此在整个class声明完成之后,才对inline 成员函数内部的数据成员执行绑定操作。
但是, 这对于 member function 的形参 argument list,list 中的名称还是会在它们第一次遭遇时被适当地 决定了resolve。 因此在 extern 和 nested type names 之间的非直觉绑定还是会发生:
typedef int length;
class Point3d
{
public:
//length 被 resolve 为 global
// _val 被正确 resolve 为 Point3d::_val
void mumble(length val) { _val = val; }
length mumble() { return _val; }
private:
//这样就导致编译器显示先前的参考操作不合法
typedef float length; //length 必须在 class 对它的第一个使用操作之前被发现
length _val;
};
把 nested type 声明放在 class 的起始处, 就可以避免导致的非直觉绑定。

浙公网安备 33010602011771号