小言_互联网的博客

C++(对象模型):04---Data之(Data Member的绑定(类内成员与全局数据的冲突性问题))

248人阅读  评论(0)

一、考察下面的一个例子


  
  1. //某个foo.h头文件,有如下声明
  2. extern float x;

  
  1. //在Point3d.h文件中
  2. #include "foo.h"
  3. class Point3d
  4. {
  5. public:
  6. Point3d( float, float, float);
  7. //问题:这里返回的是哪一个x哪?
  8. float X()const { return x; }
  9. void X(float new_X) { x = new_X; }
  10. //...
  11. private:
  12. float x, y, z;
  13. };

问题思考

  • 在上面的Point3d.h头文件中,第一个X()成员函数会返回什么哪?class外部的(x)哪?还是class内部的数据成员x哪?

问题解析

  • 在今天看来,第一个X()成员函数时内部的x数据成员

二、早期C++标准的数据成员绑定

  • 为了防止类内数据成员与全局数据成员产生冲突,早期C++设置了下面两种防御性程序设计风格

风格①

  • 把所有的数据成员放在class声明起头处,以确保正确的绑定

   
  1. #include "foo.h"
  2. class Point3d
  3. {
  4. float x, y, z;
  5. public:
  6. //...
  7. float X()const { return x; }
  8. //...
  9. };

风格②

  • 把所有的内联函数,不管大小都放在class声明之外

   
  1. #include "foo.h"
  2. class Point3d
  3. {
  4. float x, y, z;
  5. public:
  6. //...
  7. float X()const;
  8. //...
  9. };
  10. inline float Point3d::X() const
  11. {
  12. return x;
  13. }
  • 总结:上面这种设计风格到今天还存在,虽然在C++2.0之后这种必要性就消失了。这些古老的语言规则被称为“member rewriting rule”,大意是“一个inline函数,在整个class声明未被完全看见之前,是不会被评估求值的”

三、现代C++标准的数据成员绑定规则

  • C++标准精炼上面的“rewriting rule”,定义了如下的规则:
    • 对数据成员的分析,只有在整个class的声明都出现了才开始(直到出现classs右大花括号“}”)

演示说明


   
  1. extern int x;
  2. class Point3d
  3. {
  4. public:
  5. //...
  6. //该函数本身的分析不会立即执行,而是等到class声明的右大括号“}”出现才开始
  7. float X()const { return x; }
  8. //...
  9. private:
  10. float x, y, z;
  11. };
  12. //在此,class的分析才开始,所以X()成员函数分析的是自身类的x数据成员,而不是全局的x

四、参数列表分析

  • 通过下面这些演示案例,为了说明本文所介绍的“Data Member的绑定”是与数据成员有关的规则,而其他规则则不可以使用,需要具体分析
  • 参数列表的规则与上面的数据成员分析规则有一些不一样(请看下面的演示案例)

演示案例①

  •  尽管类型也使用typedef进行了类型声明,但是两个mumble成员函数使用的都是全局的typedef声明

   
  1. typedef int length; //全局
  2. class Point3d
  3. {
  4. public:
  5. void mumble(length val) { _val = val; }
  6. length mumble() { return _val; }
  7. private:
  8. typedef float length; //局部
  9. length _val;
  10. };

演示案例②

  •  为了演示上面那个演示案例的正确性,我们将全局typedef注释掉,程序会报错

   
  1. //typedef int length;
  2. class Point3d
  3. {
  4. public:
  5. void mumble(length val) { _val = val; }
  6. length mumble() { return _val; }
  7. private:
  8. typedef float length; //局部
  9. length _val;
  10. };

演示案例③

  • 为了正确使用类内的typedef声明,我们应该将类内typedef放置在class声明的最前面
  • 下面的程序是语义正确的

   
  1. typedef int length; //全局
  2. class Point3d
  3. {
  4. private:
  5. typedef float length; //局部
  6. length _val;
  7. public:
  8. void mumble(length val) { _val = val; }
  9. length mumble() { return _val;
  10. };

 

 


转载:https://blog.csdn.net/qq_41453285/article/details/103807683
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场