我们有一个存储类,类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
};
说我有这段代码:
示例中的第6行修改了Person
的地址
当我想根据新地址(“y”)获得Person
时,PersonPool
将无法返回此Person
。
它“不知道”地址已被修改,并且仍将旧地址“x”保留为该Person实例的键。
PersonPool
增强的建议:Person
的用户修改(即使m_name可能被修改),该怎么办PersonPool
:PersonPool
中的 Person 的任何修改都必须使用PersonPool
提供的 new 功能完成
的问题:
Person
中复制PersonPool
接口。我们当然不想这样做。 您能想到更好的PersonPool
实施。是否有可能调整我的建议并摆脱问题。
感谢您的时间!
答案 0 :(得分:1)
我无法确定这是否是学术活动。无论如何,很难确定具体的存储实现将为您提供最佳性能。这取决于许多因素,包括(但不限于):
我将采用的方法是设计类接口以满足所有使用要求,构建一些简单的性能测试,并开始比较不同存储实现的相对性能。从最简单的实现开始,如果需要,继续进行更复杂的优化(避免过早优化!)。
这是封装的好处:您可以自由更改内部实现细节,而不会影响接口的用户。
此外,使用地址作为唯一键似乎不起作用。如果您实际上是在对现实世界数据进行建模,那么多个人不可能拥有相同的地址(或名称或电话号码)吗?我可能会使用内部函数来封装唯一键的细节。
关于类接口的一些建议:
// use typedefs to make changes easier
typedef string KEY_TYPE;
typedef map<KEY_TYPE, Person> PERSON_POOL;
typedef vector<Person> PERSONS;
class PersonPool
{
public:
void add_person(const Person& p);
void update_person(const Person& p);
Person get_person(string name, string address);
void remove_person(string name, string address);
bool person_exists(string name, string address);
// find zero or more persons
PERSONS get_persons_by_name(string name);
PERSONS get_persons_by_address(string address);
PERSONS get_persons_by_number(string number);
private:
KEY_TYPE get_key(string name, string address);
KEY_TYPE get_key(const Person &p);
PERSON_POOL m_persons;
};
示例实施:
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";
}
无论如何,祝你的项目好运。
答案 1 :(得分:0)
使用带地址的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);
}
};