假设我们要创建std::map
的子类,并且需要捕获容器中的所有插入和删除操作。例如,为了保存有关容器中存在的键的一些特定于应用程序的信息。
如果可能的话,最简单的方法是什么?
可能,最明显的方法是重写所有执行插入和删除操作的方法和操作符。但我想,在这条路上,有些东西很容易被忽视,不是吗?
一般情况下没有办法这样做。继承不是一个好主意,因为std::map
不是多态的,并且当您使用指向映射的指针时不会发生虚拟分派。这时,您还不如使用一个简单的包装器类,这样可以省去很多麻烦:
#include <iostream>
#include <map>
template <class Key, class Value>
struct Map {
private:
std::map<Key, Value> _data;
public:
template <class Y, class T>
void insert(Y &&key, T &&val) {
std::cout << "[" << key << "] = " << val << "n";
_data.insert_or_assign(std::forward<Y>(key), std::forward<T>(val));
}
void remove(Key const &key) {
auto const it = _data.find(key);
if (it == _data.end())
return;
std::cout << "[" << key << "] -> removedn";
_data.erase(it);
}
Value *get(Key const &key) {
auto const it = _data.find(key);
if (it == _data.end())
return nullptr;
return &it->second;
}
};
int main() {
Map<int, char const *> map;
map.insert(10, "hello");
map.insert(1, "world");
map.remove(1);
map.remove(10);
map.remove(999);
}
短答:没有
c++标准库数据结构并不是为支持这个用例而设计的。您可以子类化并尝试重写,但这不会像您期望的那样工作。事实上,你会得到一个错误,在编译时,如果你做正确的帮助关键字override
。问题是std::map
方法不是virtual
,所以它们不支持所谓的晚期绑定。使用指向std::map
的引用和指针的函数将继续使用std::map
方法,即使在传递std::map
子类的实例的情况下。
您唯一的选择是创建一个全新的类your_map
,其中包含std::map
所需方法的子集,并将该任务委托给std::map
的内部实例,如Ayxan Haqverdili的答案所示。不幸的是,这种解决方案需要您更改与代码一起工作的函数的签名,将std::map &
参数替换为your_map &
,这可能并不总是可行的。