Ich hatte eine bidirektionale Objektverknüpfung mit rohen Zeigern implementiert und es funktionierte ohne Fehler. Dann entschied ich mich zu meinen Code mit Smart-Pointer Refactoring und ganz plötzlich ein String Mitglied (depName) von einer der Klassen (Abteilung) ist nicht mehr accesssible nach Objektinitialisierung. Ich habe überprüft, ob der Parameter korrekt übergeben wird und im Konstruktor ist alles in Ordnung. Das Mitglied erhält den beabsichtigten Wert. Aber danach ist es nicht mehr zugänglich und zusätzlich zu diesem der Code, der zuvor reibungslos lief, stürzt jetzt ab. Ich habe keine Ahnung warum.C++ bidirektionale Zuordnung: Objektzugriff mit intelligenten Zeigern scheint die Instanz zu beschädigen
EDIT: Das gleiche scheint zu dem String-Variablen-Namen für die Manager-Klasse verwendet wird. ENDE BEARBEITEN
- Der Code kompiliert ohne Fehler oder sogar Warnungen.
- Ich arbeite mit Qt Creator 3.3.0 und Mingw Compiler 5.4.0
- Das System behauptet, es gibt einen "Segmentierung Fehler".
Dies ist mein Code (sorry, es ist viel - ich habe es reduziert so viel wie ich es gewagt):
in den Header-Dateien:
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;
};
in den cpp Dateien : 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;
}
manager.cpp
//---------------------
float Manager::getSalary() const
{
return salary;
}
//----------------------------------
string Manager::getName() const
{
return name;
}
//----------------------------------
Manager::Manager(string n, float s, float bon)
:name(n),salary(s), bonus(bon)
{}
//----------------------------------
Manager::~Manager(){}
//----------------------------------
float Manager::income()const
{
return (salary + calcBonus());
}
//----------------------------------
string Manager::toString() const
{
stringstream ss;
ss << name << "\n heads the department ";
shared_ptr<Department> dep = myDepartment.lock();
if(dep !=nullptr)
ss<< dep->getDepName();
else ss << " NONE ";
ss << "\nBonus: " << calcBonus();
ss << "\nIncome: " << income();
return ss.str();
}
//----------------------------------
double Manager::calcBonus()const
{
shared_ptr<Department> dep = myDepartment.lock();
if(dep != nullptr)
return dep->sumOfIncome()* bonus;
else
return 0;
}
//----------------------------------
shared_ptr<Department> Manager::getMyDepartment() const
{
// if(!meineAbteilung->expired())
return myDepartment.lock();
}
//----------------------------------
void Manager::setMyDepartment(shared_ptr<Department> dep)
{
myDepartment = dep;
}
//----------------------------------
Testlauf:
int main(){
shared_ptr<Department> itDepartment
= make_shared<Department>("IT",make_shared<Manager>("Julia", 66066, 0.15));
itDepartment->show();
return 0;
}
Es wäre hilfreich, ein Backtrace des Absturzes, den Sie erwähnt haben, einzuschließen. –
Ich bin mir nicht sicher, wie ich das liefern soll. Bedeutet das eine Stapelverfolgung? Ich weiß, wie man das in Eclipse (Java) macht, aber nicht in QT. Aber ich kann diese Informationen liefern: Das Programm stürzt ab, um den Namen des Managers in der Show-Methode zugreifen, die auch nicht mehr verfügbar ist. Das System gibt an, dass ein Segmentierungsfehler vorliegt. – schulefant
Sie könnten es auf gdb ausführen, aber, wenn Sie es grafisch machen wollen, führen Sie einfach das Projekt im Debug-Modus ('F5' auf Qt Creator) und es wird aufhören, wenn es abstürzt. Dann zeigt es Ihnen den Callstack. Mehr Infos hier: http://doc.qt.io/qtcreator/creator-debug-mode.html –