我有一个抽象类(parent,并从中创建了派生类(child),如下所示:
class parent {
public:
virtual string print()=0;
};
template<class T>
class child: public parent{
private:
unordered_map<string, parent*> children;
public:
parent *&operator[](string name) {
return children[name];
}
virtual string print(){
//some jobs...
}
}
好。现在,我使用如下所示的派生类:
child<string> a;
a["test"]->print();
并且问题显示出来。
我认为问题是unordered_map :: []运算符创建了parent类的实例,而不是我想要的child类的实例。
如何告诉unordered_map将新项目创建为child
假设您有一个std::unordered_map<std::string, int>
,并且执行以下操作:
std::unordered_map<std::string, int> m;
std::cout << m["hello"];
std::cout << m["key1"];
以上程序不会产生任何警告或错误。实际上,它将输出00
。两个零。那么,这里发生了什么?
unordered_map
或map
operator[]
插入一个值,如果键不存在。这是C ++中意外错误的最大来源之一。在上述情况下,"hello"
或"key1"
不存在,因此它们是使用value
默认值初始化为0
的原位创建的。
总是在使用operator[]
之前确保您尝试访问的值是否存在。实际上,如果要执行读取,最好使用.at()
成员函数。
固定代码:
child<string> a; a["test"] = new child<string>; a["test"]->print();
您可以通过更改
operator[]
功能来进一步防止此行为:
parent *&operator[](string name) {
if (children.find(name) == children.end()) // does it exist?
children[name] = new child<T>; // if it doesn't, create a new one.
return children[name];
}