深度探索C++对象模型------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) {x = new_x;}
            //....
        private:
            float x,y,z;
            .......
       };
        
      如果我问你Point3D::X()传回哪一个x?是class 内部的那个?还是外部那个?目前正确的回答是内部的,但是并不是从来是就是正确的。
       在C++最早期的编译器,如果在Point3D::X()的两个函数实例中对x取用操作,该操作将会指向global x object !

        因此早期C++提出了两种防御机制。
        1.把所有的Data member 放在class声明起头处,以确保正确的绑定。
        class Point3D{
                float x,y,z;
            public:
                float X() const {return x;}
                ......
        };
        2.把所有的inline functions,不管大小都放在class声明之处。
        class Point3D{
            public:
                //防御性程序设计风格2
                //把所有的inline functions都移到class之外。
                Point3D();    
                float X();
                void X(float new_a);
                ........
         };
        inline float Point3D::X() const{
            return x;
        }
        ........
        这种程序设计风格事实上到今天还存在,虽然他们的必要性自从C++2.0之后就消失了。
        C++ standard以member scope resolution rule来提炼这个rewriting rule,其效果是,如果一个inline函数在class声明之后立刻被定义的话,那么就还是对其评估求值,也就是说当一个人写下这样的代码:
        extern int x;
        class Point3D{
            public:
                ....
                //对函数本体的分析将延迟,直到class声明的右大括号出现才开始
                float X() const{ return x;}
                ......
            private :
                float x;
                .....
        };
        //事实上,分析在这里进行
        
        对member function本体的分析,会直到整个class的声明都出现了才开始,因此在一个inline member function躯体之内的一个Datamember绑定操作,会在整个class 声明完成之后才发生。

        然而,这对于member function 的argument list并不为真,Argument list 中 的名称还是会在它们第一次遭遇是被适当地决议(resolved)完成,因此在extern 和nested type name 之间的非直觉绑定操作还是会发生。
        
        typedef int  length;
        
        class Point3D{    

            public:
                //length被决议为global
                //_val被决议为Point3D::_val
                void mumble(length val){ _val = val;}
                length mumble() { return _val;}
            private:
                //length 必须在本class对它的第一个参考操作之前被看见
                //这样声明将使先前操作不合法
                typedef float length;
                length _val;
                .......
            }
        
        上述这个语言状况,任然需要某种防御性风格,请总是把nested type声明放在class的起始处。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值