要使用继承来实现这一点,您可以将其Key
视为一种数据类型,专门设计为映射/多映射实现中的键。Key
继承自Object
,但它可能提供自己的特定于键的函数,例如 - 例如 -repr()
生成地图用于某些特定于地图的操作的表示的函数(可能作为散列或排序或其他的基础) .
map/multimap 必须以这样一种方式使用,即Key
对象被存储为指针(或std::unique_ptr
,或std::shared_ptr
,或任何适当的),而不是作为Key
对象的副本。
所以我们有:
struct Object
{
virtual ~Object()
{ }
};
/* Key class. Pointers of this type are inserted
into the map. */
class Key : public Object
{
public:
/* Must be supported by all keys: */
virtual std::string repr() const = 0;
};
我们还假设对象有一个单独的定义Person
:
struct Person : Object
{
Person(const std::string &name)
: name_(name)
{ }
std::string name_;
};
根据您的规范,有两种风格Key
:一种表示字符串并且必须使用字符串进行初始化,另一种表示人员并且必须由人员指针初始化(我假设人员键实际上并不拥有这些指针,因此您需要确保它们指向的人员对象只要人员密钥存在就保持活动状态)。
我们通过专门针对Key
两个派生类 aPersonKey
和 a来实现这一点StringKey
:
class PersonKey : public Key
{
public:
PersonKey(Person *person_ptr)
: Key() , person_ptr_(person_ptr)
{ }
virtual std::string repr() const
{
if (person_ptr_ != 0)
return std::string("Person/") + person_ptr_->name_;
else
return "<NUL>";
}
private:
Person *person_ptr_;
};
class StringKey : public Key
{
public:
StringKey(const std::string &str)
: Key() , str_(str)
{ }
virtual std::string repr() const
{
return str_;
}
private:
std::string str_;
};
当您插入地图/多图时,您会生成Key
对象(您表示为Key*
orKey&
或std::unique_ptr<Key>
)。当你想插入一个字符串时,你将它们生成为StringKey
对象,当你想将它们作为人指针插入时,你使用PersonKey
- 但是你插入的键的数据类型不会反映专业化。
这是一个通用Key
对象的示例(实现为std::unique_ptr<Key>
,但Key*
如果您不怕内存泄漏,则可以使用):
int main()
{
/* General key object: */
std::unique_ptr<Key> mykey;
/* Now it points to a string-key, initialized using
a string, as required: */
mykey.reset(new StringKey("hello"));
std::cout << "repr(mykey) == \""
<< mykey->repr()
<< '"'
<< std::endl;
/* Now the same key object is made to refer to
a person object: */
Person person("me");
mykey.reset(new PersonKey(&person));
std::cout << "repr(mykey) == \""
<< mykey->repr()
<< '"'
<< std::endl;
return 0;
}
上面代码的必要标题是:
#include <iostream>
#include <memory>
#include <string>
(但memory
仅在我使用时才需要,std::unique_ptr
实际上并不是解决您的问题所必需的。)