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

    (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++多态性中基类析构函数声明为虚函数

    先来看几段程序例子:

    • 将基类析构函数声明为虚函数
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    #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;
    }

    运行结果:

    • 不将基类析构函数声明为虚函数:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    #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,会调用静态类型即基类的析构函数,而不会调用派生类的析构函数。

    (以上纯属个人理解)

    总结:

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

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

    转载:https://www.cnblogs.com/AndyJee/p/4575810.html

  • 相关阅读:
    mysql常用基本命令
    mysql8.0.13下载与安装图文教程
    k8s ingress 增加跨域配置
    Jenkins 备份恢复插件 thinBackup 使用
    k8s HA master 节点宕机修复
    nginx 跨域问题解决
    mongodb 3.4.24 主从复制
    k8s 线上安装 jenkins并结合 jenkinsfile 实现 helm 自动化部署
    k8s helm 运用与自建helm仓库chartmuseum
    centos6 源码安装 unzip
  • 原文地址:https://www.cnblogs.com/shaonianpi/p/13035815.html
Copyright © 2011-2022 走看看