C++boolan part2

关于vptr/vtbl

关于vptr和vtbl(取至侯捷老师)

1.只要类中存在虚函数(vptr),则一定有一根虚指针(就算有10000个虚函数也只存在一个虚指针),其内容指向虚表(vtbl)。
2.虚表的作用是存放虚函数的指针,子类在覆写虚函数后存放地址不同。
3.用指针调用虚函数的过程为动态绑定,用代码语言可以表示为

(*(p->vptr)[n])(p);
//或者
(*p->vptr[n])(p);
//p指针调用虚指针找到虚表,然后根据下标n找到具体函数地址,
//再转到具体函数

关于动态绑定与静态绑定

以下转至http://blog.csdn.net/chgaowei/article/details/6427731
需要理解四个名词:
1、对象的静态类型:对象在声明时采用的类型。是在编译期确定的。
2、对象的动态类型:目前所指对象的类型。是在运行期决定的。对象的动态类型可以更改,但是静态类型无法更改。
关于对象的静态类型和动态类型,看一个示例:

class B  
{  
}  
class C : public B  
{  
}  
class D : public B  
{  
}  
D* pD = new D();//pD的静态类型是它声明的类型D*,动态类型也是D*  
B* pB = pD;//pB的静态类型是它声明的类型B*,动态类型是pB所指向的对象pD的类型D*  
C* pC = new C();  
pB = pC;//pB的动态类型是可以更改的,现在它的动态类型是C*

3、静态绑定:绑定的是对象的静态类型,某特性(比如函数)依赖于对象的静态类型,发生在编译期。
4、动态绑定:绑定的是对象的动态类型,某特性(比如函数)依赖于对象的动态类型,发生在运行期。

class B  
{  
    void DoSomething();  
    virtual void vfun();  
}  
class C : public B  
{  
    void DoSomething();//首先说明一下,这个子类重新定义了父类的no-virtual函数,这是一个不好的设计,会导致名称遮掩;这里只是为了说明动态绑定和静态绑定才这样使用。  
    virtual void vfun();  
}  
class D : public B  
{  
    void DoSomething();  
    virtual void vfun();  
}  
D* pD = new D();  
B* pB = pD;  

让我们看一下,pD->DoSomething()和pB->DoSomething()调用的是同一个函数吗?
不是的,虽然pD和pB都指向同一个对象。因为函数DoSomething是一个no-virtual函数,它是静态绑定的,也就是编译器会在编译期根据对象的静态类型来选择函数。pD的静态类型是D,那么编译器在处理pD->DoSomething()的时候会将它指向D::DoSomething()。同理,pB的静态类型是B,那pB->DoSomething()调用的就是B::DoSomething()。

让我们再来看一下,pD->vfun()和pB->vfun()调用的是同一个函数吗?
是的。因为vfun是一个虚函数,它动态绑定的,也就是说它绑定的是对象的动态类型,pB和pD虽然静态类型不同,但是他们同时指向一个对象,他们的动态类型是相同的,都是D*,所以,他们的调用的是同一个函数:D::vfun()。

上面都是针对对象指针的情况,对于引用(reference)的情况同样适用。

指针和引用的动态类型和静态类型可能会不一致,但是对象的动态类型和静态类型是一致的。

总结于侯捷老师:动态绑定要满足三个条件1、必须通过指针;2、必须是向上转型;3、必须是虚函数;

关于重载new和delete(new[ ]和delete[ ])

在解决内存分配与管理时,C++允许重载new和delete来实现我们自己的存储分配方案。
当我们在重载operator new和operator delete时,我们只是改变了原来的内存分配方法。
示例如下


member operator new/delete

你可能感兴趣的:(C++boolan part2)