【问题标题】:C++ understanding constructors in inheritanceC++ 理解继承中的构造函数
【发布时间】:2021-12-08 18:14:58
【问题描述】:

我目前正在学习 C++,并想了解构造函数在继承上下文中的工作方式。这是我的父类和子类:

#include <iostream>
#include <string>

enum COLOR { Green, Blue, White, Black, Brown, };


class Animal
{
    protected:
        std::string _name;
        COLOR _color;
    public:
        Animal(): _name("unknown"){
            std::cout << "constructing Animal object " << _name << std::endl;
        }
        Animal(std::string animalName, COLOR animalColor){
            _name = animalName;
            _color = animalColor;
            std::cout << "constructing ";
            std::cout<< _color;
            std::cout << " Animal object " << _name << std::endl;
        }
        ~Animal(){
            std::cout << "destructing Animal object " << _name << std::endl;
        }
        void speak(){
            std::cout << "Animal speaks" << std::endl;
        }
        void move() const {}
    private:
};
class Mammal: public Animal{
    public:
        Mammal():Animal(){}
        Mammal(std::string mammalName, COLOR animalColor)
        :Animal(mammalName, animalColor){}
        ~Mammal(){
            std::cout << "Destructing Mammal object " << _name << std::endl;
        }
        void eat() const{
            std::cout << "Mammal eat" << std::endl;
        }

    private:
};

class Dog: public Mammal{
    public:
        Dog():Mammal(){}
        Dog(std::string dogName, COLOR dogColor)
            :Mammal(dogName, dogColor){}
        ~Dog(){
            std::cout << "Destructing Dog object " << _name << std::endl;
        }

    private:


};

这是我的主要内容:

 int main(){

    Animal a;
    a.speak();

    Animal b("Boar", Blue);
    b.speak();

    Mammal m("Monkey", Black);
    m.speak();

    Dog d("Panda", Brown);
    std::cout << "Program exiting..." << std::endl;
    return 0;
}

这是输出的样子:

constructing Animal object unknown
Animal speaks
constructing 1 Animal object Boar
Animal speaks
constructing 3 Animal object Monkey
Animal speaks
constructing 4 Animal object Panda
Program exiting...
Destructing Dog object Panda
Destructing Mammal object Panda
destructing Animal object Panda
Destructing Mammal object Monkey
destructing Animal object Monkey
destructing Animal object Boar
destructing Animal object unknown

Process returned 0 (0x0)   execution time : 1.102 s

我很好奇的是析构函数语句。似乎如果我将析构函数添加到子类(构造函数似乎也是如此),您会看到子类的析构函数运行,然后父类的析构函数也运行。 因此你的析构函数顺序是 Dog -> Mammal -> Animal。这是什么意思? 这是否意味着 C++ 已经初始化了 3 个实例化对象只是为了生成 1 个 Dog 对象? 析构函数(和构造函数)的流程在这里如何工作?

【问题讨论】:

    标签: c++ inheritance constructor polymorphism


    【解决方案1】:

    这是否意味着 C++ 已经初始化了 3 个实例化对象只是为了生成 1 个 Dog 对象?

    没有。这意味着,派生类隐式调用父类析构函数,因此它们仍然有机会释放私有资源。在这种情况下,所有三个析构函数都被调用,因为只有一个 Dog 类的实例正在被析构。

    构造函数似乎也是如此

    构造函数有类似的概念,但不像析构函数,你经常显式调用它们,所以这并不奇怪。

    【讨论】:

      【解决方案2】:

      constructing 对象使用特定序列,destroying them 使用相反序列。

      施工:

      初始化顺序

      成员初始化器在列表中的顺序无关:实际初始化顺序如下:

      1. 如果构造函数是用于最派生类的,则虚基按照它们在基类声明的深度优先从左到右遍历中出现的顺序进行初始化(从左到右是指外观)在基本说明符列表中)
      2. 然后,直接基会按照从左到右的顺序初始化,因为它们出现在此类的基说明符列表中
      3. 然后,按类定义中的声明顺序初始化非静态数据成员。
      4. 最后,构造函数的主体被执行

      为了毁灭:

      销毁顺序

      无论是用户定义的还是隐式定义的析构函数,在析构函数体执行完毕后,编译器都会为类的所有非静态非变体成员调用析构函数,按照声明的相反顺序,然后调用所有直接非虚拟基类的析构函数以相反的构造顺序(依次调用其成员及其基类的析构函数等),然后,如果该对象属于最派生类,则调用析构函数所有虚拟基地。

      即使直接调用析构函数(例如obj.~Foo();),~Foo() 中的 return 语句也不会立即将控制权返回给调用者:它首先调用所有这些成员析构函数和基析构函数。

      本质上,构造首先构建基类部分,然后是派生类,然后销毁以相反的顺序销毁它。

      在您的代码中,首先执行Dog 析构函数的主体,然后执行Mammal 析构函数。首先执行它的主体,然后执行 Animal 基的析构函数。

      【讨论】:

        猜你喜欢
        • 2017-08-09
        • 1970-01-01
        • 2019-01-21
        • 2015-06-09
        • 2018-06-28
        • 1970-01-01
        • 1970-01-01
        • 2020-04-22
        • 2012-11-14
        相关资源
        最近更新 更多