• 转载:(C++)浅谈多态基类析构函数声明为虚函数


    原博文:https://www.cnblogs.com/AndyJee/p/4575810.html

    主要内容:

    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

  • 相关阅读:
    LeetCode-494. Target Sum(DFS&DP)
    页面过渡 页面切换
    推荐几款制作网页滚动动画的 JavaScript 库
    Loda Button
    在百度地图或谷歌地图给中国各省着色并高亮显示
    TweenMax.js
    anime.js 简单入门教程
    用nrm一键切换npm源
    阿里巴巴26个前端开源项目
    Git使用教程,最详细,最傻瓜,最浅显,真正手把手教
  • 原文地址:https://www.cnblogs.com/strivingforever/p/8622339.html
Copyright © 2020-2023  润新知