2013-02-10 61 views
2

我已经实现了下面的程序来了解组合设计模式。我也使用了C++ 11中的几个概念。但对我来说糟糕的是,这个程序在运行时出现分段错误。我试着用GDB进行调试,结果发现getID()函数存在一些问题。无法理解为什么分段错误?

#0 0x08049a12 in Employee::getID (this=0x0) at Composite.cpp:27 
27  int getID(){return ID;} 

但我仍然无法理解该功能出了什么问题?感谢有人能帮助。

#include <iostream> 
#include <memory> 
#include <string> 
#include <vector> 
#include <algorithm> 

using namespace std; 

class Employee 
{ 
    protected: 
    int ID; 
    string Name; 
    string Role; 

    public: 
    Employee(int empID, string empName, string empRole) 
    { 
     ID=empID; 
     Name=empName; 
     Role=empRole; 
    } 
    virtual void showDetails()=0; 
    virtual void addWorker(shared_ptr<Employee> newWorker)=0; 
    virtual void deleteWorker(shared_ptr<Employee> employee)=0; 
    virtual ~Employee(){} 
    int getID(){return ID;} 
}; 

class Worker : public Employee 
{ 
    public: 
    Worker(int empID, string empName, string empRole) 
     : Employee(empID, empName, empRole) {} 

    void showDetails() 
    { 
     cout<<Name<<" ("<<ID<<") "<<Role<<endl; 
    } 

    void addWorker(shared_ptr<Employee> newWorker){}; 
    void deleteWorker(shared_ptr<Employee> employee){}; 
}; 

class Supervisor : public Employee 
{ 
    private: 
    vector<shared_ptr<Employee>> myTeam; 

    public: 
    Supervisor(int empID, string empName, string empRole) 
     : Employee(empID, empName, empRole) {} 

    void addWorker(shared_ptr<Employee> newWorker) 
    { 
     myTeam.push_back(newWorker); 
    } 

    void deleteWorker(shared_ptr<Employee> employee) 
    { 
     int pos=0; 
     for (auto temp : myTeam) 
     { 
     if (temp->getID()!=employee->getID()) 
      ++pos; 
     else 
      myTeam.erase(myTeam.begin()+pos); 
     } 
    } 

    void showDetails() 
    { 
     cout<<Name<<" ("<<ID<<") "<<Role<<" ---->"<<endl; 
     for (auto worker : myTeam) 
     { 
     worker->showDetails(); 
     } 
     cout<<endl; 
    } 
}; 

int main() 
{ 
    shared_ptr<Employee> Tushar(new Worker(376653,"Tushar Shah","Team mate")); 
    shared_ptr<Employee> Ranjeet(new Worker(469725,"Ranjeet Aglawe","Team mate")); 
    shared_ptr<Employee> Kiran(new Supervisor(137581,"Kiran Asher","Manager")); 
    shared_ptr<Employee> Namita(new Supervisor(122110,"Namita Gawde","Manager")); 
    shared_ptr<Employee> Rumman(new Supervisor(122022,"Rumman Sayed","Manager")); 
    shared_ptr<Employee> Rajendra(new Supervisor(111109,"Rajendra Redkar","Manager")); 
    shared_ptr<Employee> Sameer(new Supervisor(106213,"Sameer Rajadhyax","Group Lead")); 

    Kiran->addWorker(Tushar); 
    Kiran->addWorker(Ranjeet); 
    Sameer->addWorker(Kiran); 
    Sameer->addWorker(Namita); 
    Sameer->addWorker(Rumman); 
    Sameer->addWorker(Rajendra); 

    Sameer->showDetails(); 

    Sameer->deleteWorker(Rumman); 
    Sameer->showDetails(); 

    return 0; 
} 
+2

问题是你有四个经理,一个组领导,只有两个工人。也许这里实现的设计模式实际上是Inversion of Control? – 2013-02-10 12:06:14

+0

问题不在于函数本身。这就是你在某个空的Employee实例上调用该非静态成员函数(注意调试器消息中的“this = 0x0”)。 – Mat 2013-02-10 12:07:50

+0

通常是一个不好的赋值 – 2013-02-10 12:08:00

回答

3

变化

else 
    myTeam.erase(myTeam.begin()+pos); 

else { 
    myTeam.erase(myTeam.begin()+pos); 
    break; 
} 

固定碰撞(demo on ideone;没有breakit crashes with SIGSEGV)。问题在于,即使在删除其中一个元素后仍继续迭代矢量,这是不允许的。

由于您要删除只有一名工人(假设ID是唯一的),所以在元素被删除后继续进行并不是一个好主意。

+0

非常感谢。该计划与您的建议修改一起工作。再次感谢。 – tshah06 2013-02-10 12:20:14

3

你的问题是C++和STL的一个非常常见的缺陷:你在迭代期间没有仔细考虑就擦除。在这里:

for (auto temp : myTeam) 
    { 
    if (temp->getID()!=employee->getID()) 
     ++pos; 
    else 
     myTeam.erase(myTeam.begin()+pos); 
    } 

这是不正确的,一般来说,从一个STL容器中删除,而迭代它。相反,考虑稍后“标记”要删除的元素,或者使用基于整数或迭代器的迭代,以便更精确地控制它。我可能会在这里使用一个简单的基于整数的for循环,因为无论如何你都有这个“pos”变量。

+0

约定的约翰。但是这个宣言主要是为了了解复合设计模式,所以我试图保持简单和快速。但我欢迎你的建议。谢谢。 – tshah06 2013-02-10 12:24:00

+0

简单而快捷,但错误。至少你有三分之二! ;-) – 2013-02-10 12:24:58

0

问题可能出在您的deleteWorker方法中。您在修改容器时迭代该容器。

我建议两个可能的解决方案

  • 找到您要在accending顺序删除,并将其储存在一个载体项目的指标之一。然后按降序迭代矢量并将其移除。
  • 将std :: remove_if与vector :: erase结合使用。你可以看到一个例子here