Qt C++;双向关联:使用智能指针的对象访问似乎会损坏实例

Qt C++;双向关联:使用智能指针的对象访问似乎会损坏实例,qt,c++11,shared-ptr,bidirectional,weak-ptr,Qt,C++11,Shared Ptr,Bidirectional,Weak Ptr,我用原始指针实现了一个双向对象关联,它工作起来没有任何缺陷。然后我决定用智能指针重构我的代码,突然间,一个类(Department)的字符串成员(depName)在对象初始化后不再可访问。我检查了参数是否正确传递,并且在构造函数中一切正常。成员获取预期的值。但是之后它不再可访问,除此之外,以前运行顺利的代码现在崩溃了。我不知道为什么 编辑:Manager类中使用的字符串变量名似乎也发生了同样的情况。结束编辑 代码编译时没有错误,甚至没有警告 我正在使用QtCreator3.3.0和mingw编

我用原始指针实现了一个双向对象关联,它工作起来没有任何缺陷。然后我决定用智能指针重构我的代码,突然间,一个类(Department)的字符串成员(depName)在对象初始化后不再可访问。我检查了参数是否正确传递,并且在构造函数中一切正常。成员获取预期的值。但是之后它不再可访问,除此之外,以前运行顺利的代码现在崩溃了。我不知道为什么

编辑:Manager类中使用的字符串变量名似乎也发生了同样的情况。结束编辑

  • 代码编译时没有错误,甚至没有警告
  • 我正在使用QtCreator3.3.0和mingw编译器5.4.0
  • 系统声称存在“分段故障”
这是我的代码(很抱歉,太多了-我尽可能减少了):

头文件中

    class Manager;
    class Department
    {
    private:
        string depName;
        shared_ptr<Manager> head;
        vector <shared_ptr<Manager>> depMembers;
    public:
        Department(string depName, shared_ptr<Manager> head);
        virtual ~Department();
        string getDepName() const;
        void setDepName(const string &value);
        void addMember(shared_ptr<Manager> newMember);
        void removeMember(shared_ptr<Manager> who);
        const shared_ptr<Manager>getHead() const;
        void setHead(shared_ptr<Manager>value);
        double sumOfIncome();
        void show();
    };
    //--------------------------------
    class Department;
    class  Manager
    {
        private:
            string name;
            float salary;
            float bonus;//Bonus ist ein Prozentsatz
            weak_ptr<Department> myDepartment;
    //        Department * myDepartment; //With this raw pointer the code still worked*
        public:
            Manager(string, float, float);
            virtual ~Manager();
            float income()const ;
            string toString()const ;
            double calcBonus() const;
            shared_ptr<Department> getMyDepartment() const;
            void setMyDepartment(shared_ptr<Department> abt);
            float getSalary() const;
            string getName() const;
    };
班级经理;
班级部
{
私人:
字符串名称;
共享ptr头;
向量组成员;
公众:
部门(字符串depName,共享\u ptr头);
虚拟部门();
字符串getDepName()常量;
void setDepName(常量字符串和值);
无效添加成员(共享的新成员);
无效删除成员(共享成员);
常量共享\u ptrgetHead()常量;
无效设定值(共享值);
双重收入();
void show();
};
//--------------------------------
班级部;
班级经理
{
私人:
字符串名;
浮动工资;
浮动奖金;//奖金在Prozentsatz
薄弱部门;
//Department*myDepartment;//使用这个原始指针,代码仍然有效*
公众:
管理器(字符串、浮点、浮点);
虚拟管理器();
浮动收入()常数;
字符串toString()常量;
双calcBonus()常量;
共享\u ptr getMyDepartment()常量;
无效设置我的部门(共享);
float getSalary()常量;
字符串getName()常量;
};
cpp文件中: department.cpp

    //---------------------------------------------------
    Department::Department(string depName, shared_ptr<Manager>head)
        :depName(depName),head(nullptr)
    {
        this->setHead(head);
        cout << "\nIn constructor parameter depName: " + depName;
        cout << "\n instancevariable " + this->depName << endl;
    }
    //--------------------------------
    Department::~Department()
    {}
    //--------------------------------
    string Department::getDepName() const
    {
        return this->depName;
    }
    //--------------------------------
    void Department::setDepName(const string &value)
    {
        depName = value;
    }
    //--------------------------------
    void Department::addMember(shared_ptr<Manager> newMember)
    {
        depMembers.push_back(newMember);
    }
    //--------------------------------
    void Department::removeMember(shared_ptr<Manager> who)
    {
        vector<shared_ptr<Manager>>::iterator itMember = depMembers.begin();
        //Iterator must be dereferenced to access data
        while( *itMember != who){
            itMember++;
        }
        if( *itMember == who)
            depMembers.erase( itMember);
    }
    //--------------------------------
    const shared_ptr<Manager> Department::getHead() const
    {
        return head;
    }
    //--------------------------------
    void Department::setHead(shared_ptr<Manager>value)
    {
        if( head != nullptr && head->getMyDepartment()!= nullptr)
            head->setMyDepartment(nullptr);//department of old head is deleted

        //new head of department assigned
        head = value;
        //bidirektionaler access
        if(head !=nullptr)
            head->setMyDepartment( shared_ptr<Department>(this));
    }
    //--------------------------------
    double Department::sumOfIncome()
    {
        double sum = 0;
        for(unsigned int i=0; i < depMembers.size(); i++){
            sum += depMembers[i]->getSalary() ;
        }
        return sum;
    }
    //--------------------------------
    void Department::show()
    {
        cout <<"----------------" << endl;
        cout << "Department: " << this->depName << " run by " << head->getName()<<endl;
        cout <<"----------------" << endl;
        cout << "Members: " << endl;
        cout <<"----------------" << endl;
        cout << head->toString() << endl;
        for( unsigned int i=0; i < depMembers.size() ; i++){
            cout <<"----------------" << endl;
            cout << depMembers[i]->toString()<< endl;
        }
        cout <<"----------------" << endl;
    }
//---------------------------------------------------
Department::Department(字符串depName,共享\u ptrhead)
:depName(depName),head(nullptr)
{
此->设定头(head);
cout getMyDepartment()!=nullptr)
head->setMyDepartment(nullptr);//删除旧head的部门
//任命新的部门主管
头=价值;
//双向存取
如果(头!=nullptr)
负责人->设置我的部门(共享);
}
//--------------------------------
双部门::SumofInome()
{
双和=0;
for(无符号整数i=0;igetSalary();
}
回报金额;
}
//--------------------------------
作废部门::显示()
{

cout它崩溃了,因为没有人拥有某些对象。这是一个巨大的危险信号:

head->setMyDepartment(shared_ptr<Department>(this));
head->setMyDepartment(共享);
有这样一个东西,
enable\u shared\u from\u this
但是你没有使用它,所以从
this
构造一个
shared\u ptr
是毫无意义的,特别是因为你允许它立即超出范围。这将调用
delete this
,而你不想这样做


有人需要从外部拥有这些对象。他们不能只拥有彼此(循环引用)。

因为没有人拥有某些对象,所以会崩溃。这是一个巨大的危险信号:

head->setMyDepartment(shared_ptr<Department>(this));
head->setMyDepartment(共享);
有这样一个东西,
enable\u shared\u from\u this
但是你没有使用它,所以从
this
构造一个
shared\u ptr
是毫无意义的,特别是因为你允许它立即超出范围。这将调用
delete this
,而你不想这样做

有人需要从外部拥有这些对象。它们不能只拥有彼此(循环引用)。

我可以将John Zwinck的答案标记为正确-(谢谢John!),但我自己需要更多信息来理解这个问题,所以我决定发布我自己的答案

我的方法有两个问题:

  • shared_ptr
    不应使用原始指针变量创建,因为从原始指针初始化
    shared_ptr
    将创建一个具有自己引用计数的新管理器对象。只有从
    shar>中创建一个新的
    shared_ptr
    时,才能使用现有的管理器对象现有管理器对象的ed_ptr
    s或
    weak_ptr
    s。(不知何故,我读的书设法省略了这一重要信息。)
    是一个原始指针
    ,因此在我的部门构造函数中创建了第二个manager对象。构造函数一离开,第二个manager对象的引用计数就减少到0-删除我刚创建完的对象。因此,决不能从此
    创建一个
    共享\u ptr
    本身。这是一个致命的缺陷
  • 由于在双向关联中,对象需要传递一个指向自身的指针,C++库包含一个类
    enable\u shared\u from\u this
    ,该类提供了一些模板魔法,可以在后台从该类创建
    shared\u ptr
    。不幸的是
    shared\u from\u this()
    在构造函数中不可用,因为对象构建尚未完成。结论是,对象c
    head->setMyDepartment(shared_ptr<Department>(this));