C++ 实现存储类以存储某个类的多个实例

C++ 实现存储类以存储某个类的多个实例,c++,class,C++,Class,我们有一个存储类,classPerson,定义如下: class Person { public: string m_name; string m_address; string m_phone_number; }; 我们希望有一个存储类,PersonPool,它存储所有Person实例 课程要求: 应该包含所有个人的实例 应提供将人员添加到池中的方法 应提供fast访问方法,以按地址删除人员 应通过地址为个人提供快速非常量 我们建议以下类别: class Person

我们有一个存储类,class
Person
,定义如下:

class Person
{
public:
    string m_name;
    string m_address;
    string m_phone_number;
};
我们希望有一个存储类,
PersonPool
,它存储所有Person实例

课程要求:

  • 应该包含所有个人的实例
  • 应提供将人员添加到池中的方法
  • 应提供fast访问方法,以按地址删除人员
  • 应通过地址为个人提供快速非常量
  • 我们建议以下类别:

    class PersonPool
    {
    public:
        void add_person(const Person& p)   { m_persons.insert(p.m_address, p); }
        bool person_exists(string address) { return m_persons.has_key(address);     }
        Person& get_person(string address) { return m_persons[address];             }
        void remove_person(string address) { m_persons.erase(address);              }
    
    private:
        map<String,Person> m_persons;  ///> key: person address; value: Person's instance
    };
    
    class人员池
    {
    公众:
    无效添加人员(const person&p){m_persons.插入(p.m_地址,p);}
    bool person_exists(字符串地址){返回m_persons.has_key(地址);}
    Person&get_Person(字符串地址){返回m_Person[地址];}
    void remove_person(字符串地址){m_person.erase(地址);}
    私人:
    映射m_persons;///>键:person地址;值:person实例
    };
    
    使用示例 假设我有这段代码:

  • 个人游泳池
  • 人p1
  • p1.m_address=“x”
  • p_池。添加_人(p1)
  • Person&p2=p_pool.get_Person(“x”)
  • p2.m_地址=“y”
  • p_pool.get_person(“y”) 问题 示例中的第6行修改了
    人的地址

    当我想根据新地址(“y”)获取
    人员时,
    人员池
    将无法返回此
    人员

    它不“知道”地址已被修改,但仍保留旧地址“x”,作为此人实例的密钥

    PersonPool
    增强建议:
  • 地图的键不应该是地址。
    问题:
    • 正确的钥匙是什么?请记住,我们需要通过地址进行快速访问
    • 如果我们选择的新密钥也被
      Person
      的用户修改了怎么办(甚至可以修改m_名称)
  • 将函数添加到
    PersonPool

    无效更新人(字符串旧地址,字符串新地址)
    问题:
    • 丑陋的。用户应该不要为我糟糕的设计而烦恼
    • 如果用户不使用此方法怎么办
  • 仅提供常量getter。必须使用
    PersonPool
    提供的新功能对存储在
    PersonPool
    中的人员进行任何修改 问题:
    • 违反了课堂要求。我们需要非常量getter
    • 即使我们放弃了这个要求,也意味着我们必须在
      PersonPool
      中复制
      Person
      接口。我们当然不想那样做
  • 问题: 你能想出一个更好的
    PersonPool
    实现吗。有没有可能改变我的建议,解决这个问题


    谢谢您抽出时间

    使用带有地址的std::map作为键不是一个好主意。这样使用向量怎么样:

    class Person
    {
    public:
        string m_name;
        string m_address;
        string m_phone_number;
        bool operator == (const Person& other)
        {
            return m_address == other.m_address;
        }
    };
    
    class PersonPool
    {
    public:
        void add_person(const Person& p)   { m_persons.push_back(p); }
        bool person_exists(string address) { return (getPerson(address) != m_persons.end());     }
        Person& get_person(string address) { return (*getPerson(address)); }
        void remove_person(string address) { m_persons.erase(getPerson(address)); }
    
    private:
        vector<Person> m_persons; 
        vector<Person>::iterator getPerson(string address)
        {
            return find(m_persons.begin(), m_persons.end(), address);
        }
    };
    
    班级人员
    {
    公众:
    字符串m_name;
    字符串m_地址;
    字符串m_电话号码;
    布尔运算符==(常量人员和其他)
    {
    返回m_地址==其他m_地址;
    }
    };
    班级人事
    {
    公众:
    void add_person(const person&p){m_persons.push_back(p)}
    bool person_存在(字符串地址){return(getPerson(地址)!=m_persons.end());}
    Person&get_Person(字符串地址){return(*getPerson(地址));}
    void remove_person(字符串地址){m_person.erase(getPerson(地址));}
    私人:
    向量m_人;
    向量::迭代器getPerson(字符串地址)
    {
    返回find(m_persons.begin(),m_persons.end(),address);
    }
    };
    
    使用带有地址的std::map作为键不是一个好主意。这样使用向量怎么样:

    class Person
    {
    public:
        string m_name;
        string m_address;
        string m_phone_number;
        bool operator == (const Person& other)
        {
            return m_address == other.m_address;
        }
    };
    
    class PersonPool
    {
    public:
        void add_person(const Person& p)   { m_persons.push_back(p); }
        bool person_exists(string address) { return (getPerson(address) != m_persons.end());     }
        Person& get_person(string address) { return (*getPerson(address)); }
        void remove_person(string address) { m_persons.erase(getPerson(address)); }
    
    private:
        vector<Person> m_persons; 
        vector<Person>::iterator getPerson(string address)
        {
            return find(m_persons.begin(), m_persons.end(), address);
        }
    };
    
    班级人员
    {
    公众:
    字符串m_name;
    字符串m_地址;
    字符串m_电话号码;
    布尔运算符==(常量人员和其他)
    {
    返回m_地址==其他m_地址;
    }
    };
    班级人事
    {
    公众:
    void add_person(const person&p){m_persons.push_back(p)}
    bool person_存在(字符串地址){return(getPerson(地址)!=m_persons.end());}
    Person&get_Person(字符串地址){return(*getPerson(地址));}
    void remove_person(字符串地址){m_person.erase(getPerson(地址));}
    私人:
    向量m_人;
    向量::迭代器getPerson(字符串地址)
    {
    返回find(m_persons.begin(),m_persons.end(),address);
    }
    };
    
    我真的不知道这是否是一项学术活动。无论如何,很难说什么特定的存储实现将为您提供最佳性能。这将取决于许多因素,包括(但不限于):

    • 数据集的大小(有多少人)
    • 数据集的内容(字符串的格式和大小)
    • 您正在使用的特定库的效率
    • 典型用法(针对查找和更新进行优化)
    我将采用的方法是设计类接口以满足所有使用要求,构建一些简单的性能测试,并开始比较不同存储实现的相对性能。从最简单的实现开始,如果需要,继续进行更复杂的优化(避免过早优化!)

    这就是封装的好处:您可以自由地更改内部实现细节,而不会影响接口的用户

    另外,使用地址作为唯一键似乎不起作用。如果您实际上是在模拟真实世界的数据,那么多人是否有可能拥有相同的地址(或姓名或电话号码)?我可能会使用一个内部函数来封装unique键的细节

    void Person::add_person(const Person& p) { m_persons.insert(get_key(p), p); } Person Person::get_person(const Person& p) { PERSON_POOL::iterator i = find(m_persons.begin(), m_persons.end(), get_key(p)); if (i != m_persons.end()) return i->second; throw "person not found"; }