C++中派生类的构造和析构顺序详解

派生类因为要调用基类, 所以构造和析构都是按照一定顺序进行;

构造的顺序是: 基(base) -> 派生(derived);即先构造基类, 再构造派生类;

因为 基类 是独立于派生类的, 即不会调用派生类中的对象, 所以应该先被生成;

如果派生类先于基类生成, 则因为无法调用基类资源, 可能生成失败;

析构的顺序是: 派生(derived) -> 基(base); 即先释放派生类, 再释放基类;

因为 派生类 需要先释放调用的基类资源, 所以应该优先释放;

如果基类先析构, 则有可能某些资源被派生类占用, 可能导致析构失败;

派生类的构造和析构顺序正好相反;

代码:

/*
 * CppPrimer.cpp
 *
 *  Created on: 2013.11.12
 *      Author: Caroline
 */

/*eclipse cdt*/

#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <cstddef>  

using namespace std;  

class Quote {
public:
    //Quote() = default;
    Quote() {
        std::cout << "this is Quote constructor" << std::endl;
    }
    Quote (const std::string& book, double sales_price) :
        bookNo (book), price (sales_price) {}
    std::string isbn() const { return bookNo; }
    virtual double net_price (std::size_t n) const { return n* price; } //虚函数
    //virtual ~Quote() = default; //动态绑定析构器
    virtual ~Quote() {
        std::cout << "this is Quote destructor" << std::endl;
    }
private:
    std::string bookNo;
protected: //受保护类型
    double price = 0.0;
};
/*更多精彩内容:http://www.bianceng.cnhttp://www.bianceng.cn/Programming/cplus/*/
class Disc_quote : public Quote { //抽象基类
public:
    //Disc_quote() = default;
    Disc_quote() {
        std::cout << "this is Disc_quote constructor" << std::endl;
    }
    Disc_quote (const std::string& book, double price, std::size_t qty, double disc) :
        Quote(book, price), quantity (qty), discount (disc) {}
    double net_price (std::size_t) const = 0; //纯虚函数
    virtual ~Disc_quote() override{
        std::cout << "this is Disc_quote destructor" << std::endl;
    }
protected:
        std::size_t quantity = 0;
        double discount = 0.0;
};  

class Bulk_quote final : public Disc_quote { //final限定词, 无法被继承
public:
    //Bulk_quote() = default;
    Bulk_quote() {
        std::cout << "this is Bulk_quote constructor" << std::endl;
    }
    Bulk_quote(const std::string& book, double p, std::size_t qty, double disc) :
        Disc_quote(book, p, qty, disc) {} //使用基类的构造器
    double net_price(std::size_t cnt) const override;
    virtual ~Bulk_quote() override{
        std::cout << "this is Bulk_quote destructor" << std::endl;
    }
};  

double Bulk_quote::net_price(std::size_t cnt) const
{
    if (cnt >= quantity)
        return cnt * (1-discount) * price;
    else
        return cnt * price;
}  

double print_total(std::ostream &os, const Quote& item, std::size_t n)
{
    double ret = item.net_price(n);
    os << "ISBN: " << item.isbn() << " # sold: " << n << " total due: " << ret << std::endl;
    return ret;
}  

int main (void) {  

    Bulk_quote* bq = new Bulk_quote;
    delete bq;  

    return 0;  

}

输出:

this is Quote constructor
this is Disc_quote constructor
this is Bulk_quote constructor
this is Bulk_quote destructor
this is Disc_quote destructor
this is Quote destructor

作者:csdn博客 Spike_King

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索include
, 派生类
, 派生
, 生成
, 资源
顺序
构造和析构的顺序、派生类的析构函数、派生类析构函数、派生类 虚析构函数、构造函数和析构函数,以便于您获取更多的相关知识。

时间: 2024-08-02 16:49:56

C++中派生类的构造和析构顺序详解的相关文章

C++聚合关系类的构造函数的调用顺序详解_C 语言

如图,表示一个聚合关系 下面就用简单的代码来实现 #pragma once class Engine { public: Engine(); ~Engine(); }; Engine.h #include <iostream> #include "Engine.h" using namespace std; Engine::Engine() { cout << "调用构造函数:Engine()" << endl; } Engine

Python中的类与对象之描述符详解

 这篇文章主要介绍了Python中的描述符详解,属于Python学习过程中类与对象的基本知识,需要的朋友可以参考下     描述符(Descriptors)是Python语言中一个深奥但却重要的一部分.它们广泛应用于Python语言的内核,熟练掌握描述符将会为Python程序员的工具箱添加一个额外的技巧.为了给接下来对描述符的讨论做一些铺垫,我将描述一些程序员可能会在日常编程活动中遇到的场景,然后我将解释描述符是什么,以及它们如何为这些场景提供优雅的解决方案.在这篇总结中,我会使用新样式类来指代

Python中的类与对象之描述符详解_python

描述符(Descriptors)是Python语言中一个深奥但却重要的一部分.它们广泛应用于Python语言的内核,熟练掌握描述符将会为Python程序员的工具箱添加一个额外的技巧.为了给接下来对描述符的讨论做一些铺垫,我将描述一些程序员可能会在日常编程活动中遇到的场景,然后我将解释描述符是什么,以及它们如何为这些场景提供优雅的解决方案.在这篇总结中,我会使用新样式类来指代Python版本. 1.假设一个程序中,我们需要对一个对象属性执行严格的类型检查.然而,Python是一种动态语言,所以并不

浅谈Java中父类与子类的加载顺序详解_java

复制代码 代码如下: class Parent {    // 静态变量    public static String p_StaticField = "父类--静态变量";    // 变量(其实这用对象更好能体同这一点,如专门写一个类的实例)     //如果这个变量放在初始化块的后面,是会报错的,因为你根本没有被初始化    public String p_Field = "父类--变量";    // 静态初始化块    static {        S

uml-UML图中怎么表达C++中派生类构造函数?

问题描述 UML图中怎么表达C++中派生类构造函数? 主要是构造函数中对基类成员初始化问题: 例如下面这句,请问怎么在UML中写出来? Teacher(string name,int age,string department,string teacherNumber):Person(name,age) 我写的是: +Teacher(name : string ,age : int ,department : string ,teacherNumber : string ):Person(nam

解读C++编程中派生类的构成和创建_C 语言

C++派生类的构成 派生类中的成员包括从基类继承过来的成员和自己增加的成员两大部分.从基类继承的成员体现了派生类从基类继承而获得的共性,而新增加的成员体现了派生类的个性.正是这些新增加的成员体现了派生类与基类的不同,体现了不同派生类之间的区别. 在基类中包括数据成员和成员函数 (或称数据与方法)两部分,派生类分为两大部分:一部分是从基类继承来的成员,另一部分是在声明派生类时增加的部分.每一部分均分别包括数据成员和成员函数. 实际上,并不是把基类的成员和派生类自己增加的成员简单地加在一起就成为派生

为什么c++基类不是虚析构函数,析构派生类对象也自动析构基类

问题描述 为什么c++基类不是虚析构函数,析构派生类对象也自动析构基类 测试环境:Win7 + VC++6.0 问题:如图,基类析构函数**不是**虚函数,但是析构派生类时,基类的析构函数也自动执行了,不是只有是虚析构函数才会自动析构基类么?? 解决方案 记得是虚的才是只执行子类不执行父类的吧. 解决方案二: 虚的才是只执行子类不执行父类 解决方案三: 虚基类的非虚基类优先于非虚基类的非虚基类 解决方案四: 子类析构,都会调用父类的.父类虚析构是为了多态的时候,能够正确调用子类的析构函数. 解决

浅谈C++中派生类对象的内存布局_C 语言

主要从三个方面来讲: 1 单一继承 2 多重继承 3 虚拟继承 1 单一继承 (1)派生类完全拥有基类的内存布局,并保证其完整性. 派生类可以看作是完整的基类的Object再加上派生类自己的Object.如果基类中没有虚成员函数,那么派生类与具有相同功能的非派生类将不带来任何性能上的差异.另外,一定要保证基类的完整性.实际内存布局由编译器自己决定,VS里,把虚指针放在最前边,接着是基类的Object,最后是派生类自己的object.举个栗子: class A { int b; char c; }

Java技术_基础技术(0003)_类执行顺序详解+实例(阿里面试题)+详细讲解+流程图

Java技术_基础技术(0001)_后台模拟调用action Java技术_基础技术(0002)_中间件启动class加载顺序(以tomcat为例) Java技术_基础技术(0003)_类执行顺序详解+实例(阿里面试题)+详细讲解+流程图 Java技术_基础技术(0004)_eclipse远程调试tomcat 基础技术: 对于java类各个成员的执行顺序,现拿出阿里的面试题作为样例(例子非常好,是用心出的题),在这里重新说明一下java类执行顺序的原则. 源码下载(包含题.结果.分析过程) 一.