深度探索C++对象模型———Data Member的绑定

3.1 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;
};

这段代码中有两个x变量,一个是全局变量:

extern float x;

另一个是类Point3d的成员变量:

Point3d::x;

那么成员函数Point3d::X()中传回的x变量属于global x object还是class内的那个x呢?

  • 对于现代编译器

    几乎所有现代编译器都是把成员函数中的x与成员变量x绑定的(在我们看来也是很自然的)。

  • 对于早期的编译器
    该成员函数Point3d::X()中的x会和全局变量x绑定。这不是我们所期待的!为此,早期的C++出现两种防御性程序设计风格:

1.把所有data members(成员变量)放在class声明起头处,以确保正确的绑定:

class Pointed
{
    // 防御性程序设计风格 #1
    // 在class声明开始先放置所有的data members
    float x, y, z;
public:
    float X() const { return x; }
    // ...etc...
};

2.把所有的inline functions(成员函数编译器默认为inline),不管大小都放在 class 声明之外:

class Point3d
{
public:
    // 防御性程序设计风格 #2
    // 把所有的inlines都移到类之外
    Pointed();
    float X() const;
    void X(float) const;
    // ...etc...
};
inline float POint3d::X() const {
    return x;
}

这样做的目的:让”成员函数中返回的变量属于global x object还是类内x”在整个class声明之后再分析,如下所示:

extern int x;
class Point3d {
public:
    //对于函数本身的分析将延迟直至
    //class声明的右括号出现才开始
    float X()const { return x; }
private:
    float x;
};
//事实上,分析在这里进行

但是,若上述成员函数带有参数列表(即使是现代编译器),变量还是会立刻分析,如下:

typedef int length;
class Point3d
{
public:
    //喔欧:length被决议(resolved)为global
    //没问题:_val被决议(resolved)为Point3d::_val
    void mumble(length val){_val = val;}
    //..
private:
    //length 必须在“本类对它的第一个参数”之前被看见
    //这样的声明将使先前的参数操作不合法
    typedef float length;
    length _val;
    //...
};

在这种情况下,(包括现代编译器)任然得使用第一种防御风格的代码,就可以确保非直觉绑定的正确性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值