zoukankan      html  css  js  c++  java
  • 析构函数中的virtual是否必要?

    我们经常听到建议要把构造函数不能为虚,析构函数最好为虚,这是为什么?

    如下例子:

    // pvtable1.cpp : 定义控制台应用程序的入口点。

    
    #include "stdafx.h"
    
    #include <iostream>
    
    using namespace std;
    
    class Base1 {
    
    public:
    
        Base1(){ cout << "Base1::Base1()" << endl; }
        ~Base1(){ cout << "Base1::~Base1()" << endl; }
    
        virtual void f() { cout << "Base1::f" << endl; }
    
        virtual void g() { cout << "Base1::g" << endl; }
    
        virtual void h() { cout << "Base1::h" << endl; }
    
    
    
    };
    
    class Base2 {
    
    public:
        Base2(){ cout << "Base2::Base2()" << endl; }
        ~Base2(){ cout << "Base2::~Base2()" << endl; }
    
        virtual void f() { cout << "Base2::f" << endl; }
    
        virtual void g() { cout << "Base2::g" << endl; }
    
        virtual void h() { cout << "Base2::h" << endl; }
    
    };
    
    
    class Base3 {
    
    public:
        Base3(){ cout << "Base3::Base3()" << endl; }
        ~Base3(){ cout << "Base3::~Base3()" << endl; }
    
        virtual void f() { cout << "Base3::f" << endl; }
    
        virtual void g() { cout << "Base3::g" << endl; }
    
        virtual void h() { cout << "Base3::h" << endl; }
    
    };
    
    
    class Derive : public Base1, public Base2, public Base3 {
    
    public:
        Derive(){ cout << "Derive::Derive()" << endl; }
        ~Derive(){ cout << "Derive::~Derive()" << endl; }
    
        virtual void f() { cout << "Derive::f" << endl; }
    
        virtual void g1() { cout << "Derive::g1" << endl; }
    
    };
    int doIt2() 
    {
    
        Base1 *pBase1 = new Derive();
    
        delete pBase1;
    
        return 0;
    
    }
    
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        doIt2();
        return 0;
    }

    当使用一个多重继承的时候,使用父类的指针删除子类的时候,发现了不能正常析构的情况,执行结果如下:

    如果在将父类的析构函数定义为虚函数,便正常了

    一个类中将所有的成员函数都尽可能地设置为虚函数总是有益的。虽然会增大开销

    下面是设置虚函数的注意事项:

    1、只有类的成员函数才能声明为虚函数。

    2、静态成员函数不能使虚函数,因为它不受限于某个对象。

    3、内联函数不能使虚函数。

    4、构造函数不能是虚函数。

    不用virtual 的几种情况:
    1、作为非公有基类。仅作为 private base class 使用的 class 不需要使用虚拟析构函数
    2、不作为接口使用的基类。
    3. 如果你可以保证这个类不被public继承(private/protected继承的话,在非friend函数/类中就无法用基类指针指向派生类了)
    4. 如果它的所有派生类(包括派生类的派生类)的析构函数都是trivial的(这里的trivial指的是在程序员的层次什么事也不做)
    5. 如果不需要用基类的指针指向派生类的对象
    在这五种情况下,不把析构函数声明为virtual都是可以的,何况效率会高一些——但前提是你得保证前提的成立——不过这些保证常常是很难100%的:谁能保证别人在派生你的类的时候,析构函数是trivial的,或者别人不用你提供的基类的指针指向派生类对象?这些常常是很难得到保证的。

  • 相关阅读:
    艾伟_转载:你知道吗?——ASP.NET的Session会导致的性能问题 狼人:
    艾伟_转载:一次挂死(hang)的处理过程及经验 狼人:
    艾伟也谈项目管理,微型项目实践感悟 狼人:
    艾伟_转载:[原创]再谈IIS与ASP.NET管道 狼人:
    艾伟_转载:企业库缓存依赖的实现基于文件依赖 狼人:
    艾伟也谈项目管理,我也发软件开发团队的思考(侧重点是人员) 狼人:
    MYSQL用户名:root
    map 和 unordered_map以char * 为key
    设计模式单例模式(singleton)
    Android允许其他应用程序启动你的Activity
  • 原文地址:https://www.cnblogs.com/liaocheng/p/4748560.html
Copyright © 2011-2022 走看看