【问题标题】:Parent hold pointer to child data member and used the data member function in destructor父持有指向子数据成员的指针并在析构函数中使用数据成员函数
【发布时间】:2016-01-17 13:25:52
【问题描述】:

我相信我发现了现有代码的错误,但它确实有效。您能帮忙验证一下我的理解是否正确吗?

它是关于一个父类持有一个指向其子类的数据对象的对象指针。在其(父)析构函数中,它使用对象指针进行函数访问。我相信当调用父析构函数时,孩子已经被析构了,所以父指针指向的对象不再有效。下面我举个例子:

我对下面代码的问题是父析构函数是否正确?

#include <iostream>
#include <string>
using namespace std;

class object {
public:

    object(string na):name(na){}

    string get_name(){
        return name;
    }

private:
    string name;
};

class parent {

public:

    ~parent(){
        cout<<"hello"<<endl;
        cout<<mp->get_name();  **//!!!! (is this correct use mp here?)**
    }
protected:
    object* mp;

};


class child:public parent {

public:

    child():m("hello"){
        parent::mp=&m;
    }


private:
    object m;
};

int main()
{

 child a;

 return 0;
}

【问题讨论】:

  • 难以捉摸的“它确实有效”是未定义行为的一个例子。

标签: c++ pointers constructor destructor


【解决方案1】:

我相信当调用父析构函数时,子已经被析构了

§ 12.4.8 将成为我最喜欢的标准引用。

在执行析构函数的主体并销毁主体内分配的任何自动对象后,类 X 的析构函数调用 X 的直接非变体非静态数据成员的析构函数(...)

成员的析构函数类 dtor 的主体之后执行,因此调用成员的成员函数是安全的。

话虽这么说......

在您的情况下,虽然 mp 完全有效,但它指向的值却不是。由于parent 析构函数在child 析构函数之后运行,因此拥有子对象的值也将被销毁,给父对象留下一个悬空指针。

【讨论】:

  • 你写的一切都是正确的,我的意思是这不是全部。是的,成员的析构函数在主体之后执行。但是,父析构函数在此之后执行。
  • @stas 谢谢你,很抱歉造成混乱。我宁愿你使用“不完整”这个词而不是“不正确”:)。例如,我认为您在我的回答中看到了一个事实问题。
  • 是的,措辞不是我的强项)
【解决方案2】:

这是不正确的。

析构函数调用顺序:

  1. child析构函数
  2. object 析构函数(因为它是 child 类的成员)
  3. parent析构函数

看看这个:parent 有一个指向 object 的指针,它是 child 类的成员。

child():m("hello"){
    parent::mp=&m;
}

所以,当您尝试通过parent 析构函数中的指针访问object 时,它已经被破坏了:

~parent(){
    cout<<"hello"<<endl;
    cout<<mp->get_name();  //!!!! this is incorrect
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多