8. 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 {x = new_x;}//...
private:float x,y,z;
};
如果我问你Point3d::X()传回哪一个x?是class内部的x,还是外部(extern)那个x?今天每个人都会回答我是内部哪一个。这个答案是正确的。但这并不一直都是正确的,而是C++2.0的Reference manual修订后才是正确的。这个古老的语言规则被称为“member rewriting rule”,大意是“一个inline函数实体,在整个class声明未被完全看见之前,是不会被评估求值(evaluated)的”。也就是说,就像下面的代码这样的效果。
extern int x;
class Point3d
{
public:...//对于函数本体的分析将会延迟,直到//class声明的右大括号出现才开始。float X() const {return x;}
private:float x;...
};
//事实上,分析在这里进行
然而。这对于member function的argument list并不是真的。Argument list中的名称还是会在他们第一次遭遇时被适当的决议(resolved)了。
typedef int length;
class Point3d
{
public://length 被决议(resolved)为global//没问题:_val被决议(resolved)为Point3d::_valvoid mumble(length val){_val = val;}length mumble(){return _val;}
private://length 必须在本class对它的第一参考操作之前被看见//这样的声明将使先前的参考操作不合法typedef float length;length _val;//...
};
上面的代码实际的过程中会编译报错。length的类型在两个member function signatures中被决议(resolve)为global typedef,也就是int。当后续再有length的nested typedef声明出现时,C++ Standard就把稍早的绑定标记为非法。