C++ 虚函数

来源:互联网 发布:停车场计费规则 java 编辑:程序博客网 时间:2024/05/01 02:49

一、虚方法
    C++不将允许CDog对象继承了基类的属性(数据)和功能(方法),然而C++还扩展了其多态性。也就是,允许将派生类对象赋值给指向基类的指针。
    CAnimal *panimal=new CDlog;
    然后可以通过这个指针来调用CAnimal类的任何方法。虚函数就可以做到这点。

  

    [root@local~ work]# ./a.out
    animal constructor
    dog constructor
    dog speek
    animal move one tesp
    dog destructor
    animal destructor

二、虚函数工作原理
    创建派生对象时,首先调用基类的构造函数,然后调用派生类的构造函数。下图说明了CDog对象被创建后的情景,注意CAnimal部分和CDog部分在内存中是相邻的。

vitual

在类创建虚方法后,这个类必须被跟踪虚方法。很多编译器创建了虚函数表。每个类都有一个虚函数表,每个类对象都有一个执行虚函数表的指针(vptr或v-pointer)。每个对象的vptr都指向v-talbe;而对于每个虚方法,v-table都包含一个指向它的指针。创建CDog的CAnimal部分时,vptr被初始化指向v-table的正确部分。如下图

vitual2

当CDog的构造函数被调用时,添加对象的CDog部分,并调整vptr指针使其指向CDog类中覆盖的虚方法。如下图

vitual3

 

 

 

使用CAnimal指针时,vptr将根据CAnimal指针指向的对象的实际类型指向正确的函数,这样调用函数speak时,将调用正确的函数。
三、通过基类指针访问派生类的方法
    如果只有派生类有该方法,基类没有对应的虚方法,则不能通过CAnimal指针来访问该方法。不过可以将CAnimal指针强制转为CDog指针,但是CAnimal不是一个CDog,这样做将是不安全的。
四、切除
    仅当通过指针或引用进行调用时,才能发挥虚函数的魔力,按值传递对象将不能发挥虚方法的魔力。
五、创建虚析构函数
     当指向派生类对象的指针被删除时将发生什么情况呢?如果析构函数时虚函数,将执行正确的操作:调用派生类的析构函数,派生类的析构函数会自动调用基类的析构函数,因此整个对象将被正确地销毁。   
     经验规则,如果类中任何一个函数都是虚函数,析构函数也应该是虚函数。
六、虚复制构造函数
    构造函数不能是虚函数,因此从技术上,不存在虚复制构造函数。然而有时候程序非常需要通过传递一个指向基类对象的指针,创建一个派生类对象的副本。一个常见的解决方法是,在基类创建一个clone方法,并将其设置为虚方法。clone方法创建当前类对象一个副本,并返回该副本。
    由于每个派生类都覆盖了clone方法,因此他将创建派生类对象的一个副本。

 

    [root@local~ work]# ./a.out          
    animal constructor
    dog constructor
    dog speek
    animal constructor
    dog copy constructor
    dog speek
    dog destructor
    animal destructor
    dog destructor
    animal destructor

七、使用虚方法的代价
     由于包含虚方法的类必须维护一个v-table,因此使用虚方法会带来一些开销。

原创粉丝点击