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 的起始处, 就可以避免导致的非直觉绑定。

posted @ 2021-04-17 14:41  点|滴  阅读(4)  评论(0)    收藏  举报