首页 > 解决方案 > 怎么可能调用了析构函数但在此之前没有构造函数?

问题描述

我目前正在学习 C++ 的面向对象特性。我写了一段代码来测试继承和多态是如何工作的。这是代码的一部分:

    class Person
{
    public:
    Person()
    {
        cout << "Person constructed\n";
    }

    virtual void introduce()
    {
        cout << "hi from person" << endl;
    }

    ~Person()
    {
        cout << "Person destructed\n";
    }
};

class Student : public Person 
{
    public:
    Student()
    {
        cout << "Student constructed\n";
    }

    void introduce()
    {
        cout << "hi from student" << endl;
    }

    ~Student()
    {
        cout << "Student destructed\n";
    }
};

class Farmer : public Person 
{
    public:
    Farmer()
    {
        cout << "Farmer constructed\n";
    }

    void introduce()
    {
        cout << "hi from farmer" << endl;
    }

    ~Farmer()
    {
        cout << "Farmer destructed\n";
    }
};

class SJW : public Student
{
    public:
    SJW()
    {
        cout << "SJW constructed\n";
    }

    ~SJW()
    {
        cout << "SJW destructed\n";
    }
};

void whoisthis3(Person object)
{
    object.introduce();
}

int main()
{
    Student mark;
    SJW bigred;
    Farmer max;

    cout << endl;

    whoisthis3(mark);
    whoisthis3(max);
    whoisthis3(bigred);

    cout << endl;

    return 0;
}

这是它产生的输出:

Person constructed
Student constructed
Person constructed
Student constructed
SJW constructed
Person constructed
Farmer constructed

hi from person
Person destructed
hi from person
Person destructed
hi from person
Person destructed

Farmer destructed
Person destructed
SJW destructed
Student destructed
Person destructed
Student destructed
Person destructed

这些派生类在开始和结束时按预期构造和销毁。但是,当 whoisthis3 方法执行时,怎么会调用 Person 析构函数呢?那里发生了什么?

标签: c++oopdestructorcopy-constructorvirtual-destructor

解决方案


考虑以下简单程序:

struct A 
{
    A() { std::cout << "construct A\n";  }
    ~A() { std::cout << "destruct A\n";  }  
};

int main()
{
  A a;
}

这打印:

constructs A
destructs A

正如预期的那样。

现在让我们添加一个简单的函数:

void f(A a) {}

并称之为:

int main()
{
  A a;
  f(a);
}

我们看到:

construct A
destruct A
destruct A

那额外的钱destruct A是从哪里来的呢?对应的在哪里construct A?答案是,当您调用 时f,会调用默认的复制构造函数。如果您在复制构造函数中打印内容,如下所示:

A(A const&) { std::cout << "copy-construct A\n"; }

然后你得到输出:

construct A
copy-construct A
destruct A
destruct A

这表明确实已经构建了 2 个对象,然后两个对象都被销毁了。

另一方面,如果f通过引用获取参数,如下所示:

void f(A& a) {}

然后不调用复制构造函数(因为没有复制),输出将是:

construct A
destruct A

推荐阅读