Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1042717
  • 博文数量: 264
  • 博客积分: 6005
  • 博客等级: 大校
  • 技术积分: 2798
  • 用 户 组: 普通用户
  • 注册时间: 2007-08-08 20:15
文章分类

全部博文(264)

文章存档

2011年(42)

2010年(213)

2009年(4)

2008年(2)

2007年(3)

分类:

2010-03-28 00:26:44

最近又把《深入探索C++对象模型》翻开来看了,看完后项做点笔记。 又苦于浪费时间就从网上找些人家做的笔记。 比我自己写的好。 呵呵就借点人家的笔记吧。
//==============================

前一篇笔记中已经说出了 类的对象实例在内存中的三种可能的内存布局,其中,最后一种是c++编译器正在使用的。这种布局的 特点如下(先抛开虚函数方面的信息,说一般的)

 

1、非静 态(non-static)数据成员,每个对象实例的内存空间里都有一份;

 

2、静态 (static)数据成员,静态和非静态的成员函数:整个内存空间里面仅有一份(对象实例的内存空 间是没有这方面的信息的)

 

原来,什么类的成员函 数,什么类的静态数据成员啊,都是全局变量和全局函数啊,是不是有种受骗的感觉啊,搞了半天,什么都是C语 言的东西啊?

 

C++ 的 目标是什么?不就是为了追求C的效率嘛?要追求C的 效率怎么办?只有用C了。C没有面向对象的 封装机制,因此,就像用户提供了面向对象的语法,然后自己在背后将面向对象的东西转为C语言中的东 西:全局变量,全局函数......所以,从本质上来说,下面的class point的定义:

 

  1. class Point  
  2. {  
  3. public:  
  4.     Point(float xval);  
  5.     ~Point();  
  6.     float x() const;  
  7.     static int PointCount();  
  8. protected:  
  9.     ostream& print( ostream &) const;  
  10.       
  11.     float _x;  
  12.     static int _point_count;  
  13. };  

 

经过编译器的转化之后, 和下面的C代码没有什么不同:

 

  1. typedef struct Point  
  2. {  
  3.     float _x;  
  4. }Point;  
  5. int _point_count;  
  6. Point_init(Point *pt);  
  7. Point_destroy(Point *pt);  
  8. Point_PointCount();  
  9. Point_x(Point *pt);  
  10. Point_print(ostream *postream, Point *pt);  

 

所以,Point的一个对象实例pt在内存布局上,和C上面的struct Point是一样的,都是只有 一个成员_x; 每个函数调用的开销都是也和你用C语 言写的东西是一样的。

 

有两点需要说明一下:

 

1、 上面那个Point_PointCount()为什么不用传指针啊?因为在C++上面对应的是static int PointCount()static成员函数是没有this指针的,它只能访 问static数据成员----对应到C的代码里面就是说,Point_PointCount() 只访问上面的全局变量_point_count,所以就不需要传指针。

 

2 C++类里面那个privateprotected的优点在C里面没有体现出来啊?是 的,但是你可以和你的开发团队里面约定只能过函数来访问结构体里面的成员,违者一次罚款50块钱, 保证有效!!再说C++里面的限定符也不见得是绝对的安全(见我的笔记之:privateprotectedpublic

 

看见了吧?从某种角度来 说,这个世界上根本就没有什么所谓面向对象,只不过说的人多了,也就有了面向对象;面向对象只是一种概念而已。离开了实现,它什么都不是~

 

或者也可以这样说,什么 工具都用来做面向对象的方法,只要你应用得当;

 

可以说,我这一系列笔记 的讲解的地方,都是围绕着这个观念来说明的----C++特 有的语法细节,来说明一个与语言无关,与技术工具无关,与平台无关的一系列的技术思想(这大概就是传说中的置之死地而后生的方法......),这个就是我读Lippman这本书时的 感受。

 

我这篇笔记,也没有什么 新的技术讲解,纯粹是忽悠人的,呵呵。但是,如果能给某些新手以一些提示的话,就算忽悠,也有一点价值。

 

现在,问题来了:说类里 面的成员函数其实是全局函数,你蒙谁呢你?如果那里真是全局函数,那么下面的两个类:

 

  1. class Point1  
  2. {  
  3. public:  
  4.     void print();  
  5. };  
  6. class Point2  
  7. {  
  8. public:  
  9.     void print();  
  10. };  
  

里面的成员函数都是print,怎么区分谁是谁啊???还有,如果真是全局函数,又怎么会有重载,运算符重载等等的东西啊?

 

......

 

...确实是一个问题,但是我也要问一下,以显得我在你们面前好像 很有学问的样子:你知道山高自有客行路,水深自有渡船人这句话是谁说的嘛? 你知道什么叫做Name Mangling嘛?

 

欲知后事如何,请看下回 分解,呵呵~

 

PS. “山 高自有客行路,水深自有渡船人这句话,是在某本小说里面的主人公对他的师傅说的,那本小说只要是 中国人都知道的,你们不妨猜上一猜,是谁说的?呵呵。

 //==========================

关于上面提到的问题,我来解答下吧, 每个类的静态成员其实都保存在全局区没错。但是名字已经变了,编译器通过某种算法,使得每个类的静态成员,或静态成员的函数在全局区唯一。当然这种算法是可逆的。 就是说要通过 “类::静态成员“ 能找到原来的类的静态成员。 


阅读(618) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~