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

  • 相关阅读:
    F4搜索帮助 带回多个值
    ALV Tree demo(WBS元素分层显示)[引用别人的]
    WDA导出文件XLS,WORD
    采购信息记录修改[BDC]
    增强:MB1A物料价格检查
    机器学习中常见优化方法汇总
    统计模型机器学习模型领域相关知识,指标概念及问题点积累
    机器学习数学知识中令人费解的notation符号注解
    线性代数的视角理解LSR(least square regression)的参数评估算法本质
    statsmodels中的summary解读(以linear regression模型为例)
  • 原文地址:https://www.cnblogs.com/shaonianpi/p/13035815.html
Copyright © 2011-2022 走看看