全部博文(20)
分类: C/C++
2012-01-31 11:15:42
To a deeper understanding of OOP, this book will be your best
choice, the book more detailed description of the procedures MFC
structure and the process of Compilation:
当一个对象以另一个对象作为初始值时,会发生什么事情.
分成了两种情况,一种是我们声明了explicit copy
constructor,这个不是这篇文章需要搞明白的(我想大家也都很明白了).我们想知道的是我们没有为class声明explicit copy
constructor函数时编译器都干了些什么.编译器会为我们合成一个copy
constructor.以便适应任何时候的对象被正确的初始化.并且我们了解了有以下四种情况class不在按位逐一进行拷贝.
1.当你设计的类声明了一个explicit
copy constructor函数时.
2.当你设计的类是由一个具有explicit copy
constructor的基类派生的时.
3.当你设计的类声明了一个或多个虚函数时.
4.当你设计的类派生自一个继承串链,这个继承串链中有一个或多个virtual
base classes时.
一般来说,一个成员的名称前面会被加上类的名称,形成唯一的命名。实际上在对成员名称做处理时,除了加上了类名,还会将参数的链表一并加上,这样才能保证结果是独一无二的。
再来看看静态成员函数。我们有这样的概念,成员函数的调用必须是用类的对象,象这样obj.fun();或者这样ptr->fun().但实际上,只有一个或多个静态数据成员被成员函数存取时才需要类的对象。类的对象提供一个指针this,用来将用到的非静态数据成员绑定到类对象对应的成员上。如果没有用到任何一个成员数据,就不需要用到this指针,也就没有必要通过类的对象来调用一个成员函数。而且我们还知道静态数据成员是在类之外的,可以被视做全局变量的,只不过它只在一个类的生命范围内可见。(参考前面的笔记)。而且一般来说我们会将静态的数据成员声明为一个非Public。这样我们便必须提供一个或多个成员函数用来存取这个成员。虽然我们可以不依靠类的对象存取静态数据成员,但是这个可以用来存取静态成员的函数确实必须绑定在类的对象上的。为了更加好的解决这个问题,cfront2.0引入了静态成员函数的概念。
静态成员函数是没有this指针的。因为它不需要通过类的对象来调用。而且它不能直接存取类中的非静态成员。并且不能够被声明为virtual,const,volatile.如果取得一个静态成员函数的地址,那么我们获得的是这个函数在内存中的位置。(非静态成员函数的地址我们获得的是一个指向这个类成员函数的指针,函数指针)。可以看到由于静态成员函数没有this指针,和非成员函数非常的相似。
在单一继承的体系中,虚函数机制是一种很有效率的机制。我们判断一个类是否支持多态,只需要看它有没有虚函数便可以了。
构造一个对象出来很简单,这是我们在编程时经常要做的事情。我理解书上的意思是为我们分析了各种不同的类,例如一个没有Copy constructor,Copy operator的类,或者有私有变量但是没有定义虚函数的类等等,当他们构造对象时也有多种情况,global,local,还有在new时,编译器都做了什么,内存的分配情况如何。搞清楚它们也很有意思。另外这好象是前面几章学到的东西的一个进一步的研究。我们找出最复杂的虚拟继承来进行一下研究。当一个类对象被构造时,实际上这个类的构造函数被调用,不论是我们自己写的,还是由编译器为我们合成的。并且编译器会背着我们做很多的扩充工作,将记录在成员初始化列表中的数据成员的初始化工作放进构造函数,如果一个数据成员没有在成员初始化列表中出现,则会调用默认的构造函数,这个类的所有基类的构造都会被调用,以基类的声明顺序。所有的虚拟基类的构造也会被调用。还要为virtual table pointers设定初始值,指向适当的virtual tables。编译器还真累做的事情还真不少。
一个对象生命结束于析构函数开始执行的时候。它的扩展形式和构造函数的扩展顺序相反。
如果有一个全局对象,并且这个对象有构造函数和析构函数的话,它需要静态的初始化操作和内存释放工作,C++是一种跨平台的编程语言,因此它的编译器需要一种可以移植的静态初始化和内存释放的方法。下面便是它的策略。
1、 为每一个需要静态初始化的档案产生一个_sit()函数,内带构造函数或内联的扩展。
2、 为每一个需要静态的内存释放操作的文件中,产生一个_std()函数,内带析构函数或内联的扩展。
3、 提供一个_main()函数,用来调用所有的_sti()函数,还有一个exit()函数调用所有的_std()函数。
局部静态对象在C++底层机制是如何构造和在内存中销毁的呢?
1、 导入一个临时对象用来保护局部静态对象的初始化操作。
2、 第一次处理时,临时对象为false,于是构造函数被调用,然后临时对象被改为true.
3、 临时对象的true或者false便成为了判断对象是否被构造的标准。
4、 根据判断的结果决定对象的析构函数是否执行。
一般来说对于new的操作都直截了当,但语言要求每一次对new的调用都必须传回一个唯一的指针,解决这个问题的办法是,传回一个指针指向一个默认为size=1的内存区块,实际上是以标准的C的malloc()来完成。同样delete也是由标准C的free()来完成。原来如此。
由此看出在程序运行的幕后编译器也做了不少的事情;进而简化了编程者在编写程序时的一些麻烦。暂时先记这么多要想了解的更深入还要对这本书细细的琢磨和阅读;经过这次努力的探索一回,虽然谈不上深入,但收获颇丰,虽然没有“漫卷诗书喜于狂”,但也有豁然开朗的感觉。相信这本书再读几遍对C++就会有更深刻的理解。