zoukankan      html  css  js  c++  java
  • (C++)浅谈多态基类析构函数声明为虚函数

    主要内容:

    1、C++类继承中的构造函数和析构函数

    2、C++多态性中的静态绑定和动态绑定

    3、C++多态性中析构函数声明为虚函数

    1、C++类继承中的构造函数和析构函数

    在C++的类继承中,

    建立对象时,首先调用基类的构造函数,然后在调用下一个派生类的构造函数,依次类推;

    析构对象时,其顺序正好与构造相反;

    具体参考文章:http://www.cnblogs.com/AndyJee/p/4575385.html

    2、C++多态性中的静态绑定和动态绑定

    对象的静态类型:对象在声明是采用的类型,在编译期确定;

    对象的动态类型:当前对象所指的类型,在运行期决定,对象的动态类型可以更改,但静态类型无法更改。

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

    具体参考文章:http://www.cnblogs.com/AndyJee/p/4575670.html

    3、C++多态性中基类析构函数声明为虚函数

    先来看几段程序例子:

    • 将基类析构函数声明为虚函数
    #include <iostream>
    using namespace std;
    
    
    class Person{
    public:
        virtual ~Person(){  //declare destructor as a virtual function
        cout << "Person::~Person()" << endl;
        }
    };
    
    class Student : public Person{
    public:
        ~Student(){     // virtual or not is OK
            cout << "Student::~Student()" << endl;
        }
    };
    
    int main(){
        Person *pt1 = new Person;
        Person *pt2 = new Student;        // base class pointer point to derived class
        // Student *pt3 = new Person;     // derived class pointer can not point to base class
        Student *pt4 = new Student;
    
        delete pt1;
        cout << "*********" << endl;
        delete pt2;
        cout << "*********" << endl;
        //delete pt3;
        //cout << "*********" << endl;
        delete pt4;
        cout << "*********" << endl;
    
        return 0;
    }
    

    运行结果:

    • 不将基类析构函数声明为虚函数:
    #include <iostream>
    using namespace std;
    
    
    class Person{
    public:
        ~Person(){  //declare destructor as a virtual function
        cout << "Person::~Person()" << endl;
        }
    };
    
    class Student : public Person{
    public:
        ~Student(){     // virtual or not is OK
            cout << "Student::~Student()" << endl;
        }
    };
    
    int main(){
        Person *pt1 = new Person;
        Person *pt2 = new Student;        // base class pointer point to derived class
        // Student *pt3 = new Person;     // derived class pointer can not point to base class
        Student *pt4 = new Student;
    
        delete pt1;
        cout << "*********" << endl;
        delete pt2;
        cout << "*********" << endl;
        //delete pt3;
        //cout << "*********" << endl;
        delete pt4;
        cout << "*********" << endl;
    
        return 0;
    }
    

    运行结果:

    可以看出:

    用基类指针指向派生类时

    在基类析构函数声明为virtual的时候,delete基类指针,会先调用派生类的析构函数,再调用基类的析构函数。

    在基类析构函数没有声明为virtual的时候,delete基类指针,只会调用基类的析构函数,而不会调用派生类的析构函数,这样会造成销毁对象的不完全。

    分析:

    Person *pt2 = new Student;

    pt2的静态类型为Person,而动态类型为Student,

    当析构函数为虚函数时,为动态绑定,delete pt2,会调用动态类型即派生类的析构函数,由于继承关系,也会调用基类的析构函数;

    而当析构函数为非虚函数时,为静态绑定,delete pt2,会调用静态类型即基类的析构函数,而不会调用派生类的析构函数。

    (以上纯属个人理解)

    总结:

    • 应该为多态基类声明虚析构器。一旦一个类包含虚函数,它就应该包含一个虚析构器,因为多态性,必定会有基类调用派生类。

    • 如果一个类不用作基类或者不需具有多态性,便不应该为它声明虚析构器。

    参考文章:

    http://www.cnblogs.com/children/archive/2012/08/13/2636956.html

  • 相关阅读:
    洛谷P1330 封锁阳光大学
    洛谷P1341 无序字母对
    Bzoj1059 [ZJOI2007]矩阵游戏
    POJ2337 Catenyms
    Bzoj2342 [Shoi2011]双倍回文
    Bzoj1009 [HNOI2008]GT考试
    Bzoj3670 [Noi2014]动物园
    POJ2406 Power Strings
    POJ 2752 Seek the Name, Seek the Fame
    POJ3522 Slim Span
  • 原文地址:https://www.cnblogs.com/AndyJee/p/4575810.html
Copyright © 2011-2022 走看看