重新解读C++

C++的构造函数
1. 类没实现,编译器提供默认构造函数
2. 类自己实现,编译器不再提供任何构造函数
3. 类实现带参数构造函数,编译器也不会提供默认构造函数
4. 在赋值重载和带参数构造函数之间,编译器优先选择构造函数。
5. 先调用基类的构造函数,再调用派生类的构造函数,析构函数是先析构派生类,再析构基类。

C++的内存布局
1. 空类大小为1个字节
class Base
{};

2. 带virtual方法的类大小必须多加上4个字节,由于virtual是需要一个vptr来指向vtable。
class Base
{
   virtual void foo() {}
};

3. 所有static的字段大小不应该算到对象当中,如
class Base
{
   public:
      static int maxValue;
};
sizeof对象出来的结果还是1个字节。

4. 所有的方法都不占有直接,如:
class Base
{
   void foo(){}
};
sizeof对象出来的结果还是1个字节。

5. 基类的布局在派生类之上

C++纯抽象类
C++中没有interface和abstract关键字(C#/Java中有),但是我们可以通过纯抽象类来实现。
class IBase
{
   virtual public void foo() = 0;
   static const int count = 0;
};

6. 析构函数为什么要用virtual声明
class Base
{
public:
 Base() {cout << "Base constructor" << endl; }
 ~Base() { cout << "Base destructor" << endl; } // 这里有没有virtual 有着明显的区别
};

class Extand : public Base
{
public:
 Extand() { cout << "Extand constrcutor" << endl; }
 ~Extand() { cout << "Extand destructor" << endl;}
};

下面是两种调用方式:
(1)
Base *p = new Extand();
delete p;
输出:
Base constructor
Extand constrcutor
Base destructor
这里少了Extand destructor,这说明virtual在析构函数中扮演了一个传递信息的角色。其实我们的本意是想得到2的结果,但是已经没有信息告诉编译器,去哪里调用派生类的析构函数了。
------------------------------------------
(2)
Extand *p = new Extand();
delete p;
输出:
Base constructor
Extand constrcutor
Extand destructor
Base destructor
------------------------------------------
那么c++是如何去实现virtual的呢?由于virtual是运行时才确定的,因此c++对包含有virtual声明的类生成一个vptr指针,指向一个vtable。当基类的某个virtual方法被派生类重写后,派生类的方法自动变为virtual, 方法地址会自动加到基类的vtable中。这样就产生了传递的效果,我们也可以有效的明确的调用到派生类的方法,在经过类型向上传递后。

posted @ 2008-04-10 10:36  moonz-wu  阅读(297)  评论(0编辑  收藏  举报