实现存储类以存储某个类的多个实例
Implement storage class to store multiple instances of some class
我们有一个存储类,类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
};
使用示例
假设我有这段代码:
- 人池p_pool;
- 人 p1;
- p1.m_address = "x";
- p_pool.add_person(p1);
- Person&p2 = p_pool.get_person("x");
- p2.m_address = "y";
- p_pool.get_person("y");
问题
示例中的第 6 行修改了 Person
的地址。
当我想根据新地址("y")获取Person
时,PersonPool
将无法返回此Person
。
它不会"知道"地址已被修改,并且仍然保留旧地址"x"作为该 Person 实例的键。
增强PersonPool
的建议:
- 地图的键不应是地址。
问题:- 什么是正确的钥匙? 请记住,我们需要按地址快速访问。
- 如果我们选择的新密钥也被
Person
的用户修改了怎么办(即使m_name可能会被修改)
- 为
PersonPool
添加函数:
无效update_person(字符串old_address,字符串new_address)
问题:- 丑。用户不应该为我的糟糕设计而烦恼。
- 如果用户不使用此方法怎么办
- 仅提供常量吸气剂。 对存储在
PersonPool
中的 Person 的任何修改都必须使用PersonPool
提供的新功能来完成问题:- 打破类要求。 我们需要非常量吸气剂
- 即使我们放弃了这个要求,这也意味着我们必须在
PersonPool
中复制Person
界面。 我们当然不想这样做。
问题:
你能想到更好的PersonPool
实现吗?是否有可能调整我的建议并摆脱问题。
谢谢你的时间!
我真的不知道这是否是一项学术练习。 无论如何,很难确定哪种特定的存储实施将为您提供最佳性能。 这将取决于许多因素,包括(但不限于):
- 数据集的大小(有多少人)
- 数据集的内容(字符串的格式和大小)
- 您正在使用的特定库的效率
- 典型用法(针对查找与更新进行优化)
我将采取的方法是设计类接口以满足所有使用需求,构建一些简单的性能测试,并开始比较不同存储实现的相对性能。 从最简单的实现开始,如果需要,继续进行更复杂的优化(避免过早优化!
这是封装的好处:您可以自由更改内部实现细节,而不会影响接口的用户。
此外,使用地址作为唯一键似乎不起作用。 如果您实际上正在对真实世界的数据进行建模,那么多个人是否可能具有相同的地址(或姓名或电话号码)? 我可能还会使用内部函数来封装唯一键的详细信息。
对类接口的一些建议:
// 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";
}
无论如何,祝你的项目好运。
使用 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);
}
};
相关文章:
- 在std::vector上存储带有模板的类实例
- 有没有办法在类实例中存储编译时常量?
- 在向量中存储实例
- 模板类是否可以相互依赖,前提是它们不尝试存储彼此的实例?
- 如何通过循环访问数组来读取和存储实例的值?
- 如何将指针存储在实例变量中,该指针被声明为指向基类的指针
- 将CV :: MAT实例存储在C 中的堆上
- 超级级别的方法称为super具有sub的str attr 实例在循环 实例中创建的方法是作为super的指针存储在向
- 如何创建一个将队列作为数据成员的类,该成员在 c++ 中存储另一个类的实例
- 我们是否应该将指向类实例的智能指针存储在大型 std::vector 中以获得更好的性能?
- 可以存储参数化类的所有有效实例吗?
- 基类的C++数组,该数组的元素中存储有派生类的实例
- 当类名存储在另一个变量中时,如何创建类的实例
- 将类实例存储在文件中
- 将所有类实例的列表存储为类中的静态数组
- 如何从字符串中存储的类型创建实例
- 实现存储类以存储某个类的多个实例
- 将 Objective-C 类实例存储在C++类中
- 使用重复将灵气存储到 std::vector 中会导致模棱两可的类模板实例化
- 如何在类构造函数中存储实例引用