C++ 实现存储类以存储某个类的多个实例
我们有一个存储类,classC++ 实现存储类以存储某个类的多个实例,c++,class,C++,Class,我们有一个存储类,classPerson,定义如下: class Person { public: string m_name; string m_address; string m_phone_number; }; 我们希望有一个存储类,PersonPool,它存储所有Person实例 课程要求: 应该包含所有个人的实例 应提供将人员添加到池中的方法 应提供fast访问方法,以按地址删除人员 应通过地址为个人提供快速非常量 我们建议以下类别: class Person
Person
,定义如下:
class Person
{
public:
string m_name;
string m_address;
string m_phone_number;
};
我们希望有一个存储类,PersonPool
,它存储所有Person实例
课程要求:
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实例
};
使用示例
假设我有这段代码:
人的地址
当我想根据新地址(“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";
}