虚函数、纯虚函数

来源:互联网 发布:数据库中各表的结构 编辑:程序博客网 时间:2024/05/19 15:26

    

      对于纯虚函数:当派生类继承了基类的时候,如果派生类中没有写基类中的虚函数,则编译的时候不会出现什么错误,但是当写了基类中的虚函数的时候,却没有使用,则在编译过程中会出现一些链接方面的错误。

     对于虚函数:当派生类继承了基类的时候,只要用派生类的对象来初始化基类就可以调用派生类里面的函数。

     纯虚函数和虚函数的区别:区别体现在定义的时候,如果是纯虚函数,则在定义的时候对纯虚函数不会有什么实现,但是虚函数会在内部有所实现。


   例如:虚函数:virtual int  add(void) {  a+b;}

              纯虚函数:virtual int add();

    下面是转载文章,原文作者申明如下:

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://ticktick.blog.51cto.com/823160/961418


疑问:什么情况下必须用虚析构?

    先看个例子:

  1. #include <iostream>  
  2. class A  
  3. {  
  4. public:  
  5.     A(){};  
  6.     ~A()  
  7.     {  
  8.         std::cout << "~A" << std::endl;  
  9.     };  
  10. private:  
  11.     int a;  
  12. };  
  13.   
  14. class B : public A  
  15. {  
  16. public:  
  17.     B(){};  
  18.     ~B()  
  19.     {  
  20.         std::cout << "~B" << std::endl;  
  21.     }  
  22. private:  
  23.     int b;  
  24. };  
  25.   
  26. int main()   
  27. {       
  28.     B b;       
  29.     return 0;  
  30. }  

    调试发现,窗口依次输出: ~B 和 ~A,也就是说,B类对象b析构的时候,先调用了B类的析构函数,然后调用了基类的析构函数。

    如果 main 函数中的代码,替换为如下呢?

  1. int main() 
  2.     A *pb = new B(); 
  3.     delete pb; 
  4.     return 0; 

    你会发现,还是依次输出了 ~B 和 ~A,也就是说,当使用子类指针指向子类对象的时候,析构的时候,依然会依次调用子类和基类的析构函数。

    如果 main 函数中的代码,替换为如下呢?

  1. int main() 
  2.     A * pa = new B(); 
  3.     delete pa; 
  4.     return 0; 

    调试发现,这份代码,只会输出 ~A, 哦,到此终于明白了,当用基类指针指向派生类对象时,如果基类析构函数不设置为 virtual 的话,则在 delete 基类指针的时候,无法成功调用子类的析构函数。这才是虚析构函数发挥作用的真正场合。

    上述代码解决方法: 把基类 A 的析构函数设置为 virtual,则可以成功实现delete pa 的时候依次调用B类和A类的析构函数了。

    那么,进一步讲,我们是否应该把所有类的析构函数都设置为虚析构呢?

    不应该,这样设置不合理,只有在该类可能作为基类的情况下,并且可能使用到多态特性的时候,才有必要把基类的析构函数设置为虚析构,否则,没有必要,因为设置为虚析构会产生额外的开销,即下一个问题:

    一个类如果把析构函数设置为 virtual 是否也会产生虚函数表?

    我们把上述代码稍微改一下: 

  1. class A  
  2. {  
  3. public:  
  4.    A(){};  
  5.    ~A()  
  6.    {  
  7.        std::cout << "~A" << std::endl;  
  8.    };  
  9.    void test() 
  10.    { 
  11.       std::cout << "~test" << std::endl; 
  12.    } 
  13. private:  
  14.     int a;  
  15. };  
  16.   
  17. int main()  
  18. {  
  19.     std::cout << sizeof(A) << std::endl;  
  20. }  

    如果 ~A 前面不加 virtual 则输出的结果是: 4

    如果 ~A 前面加   virtual 则输出的结果是: 8 

    可以得出如下结论:

   (1) 如果类没有virtual成员函数时,类的大小由数据成员大小决定

   (2) 虚析构函数也会使类产生虚函数表,并且虚函数表的大小是 4 字节


0 0
原创粉丝点击