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