我想使运算符[]
和=
重载以执行多个任务(在我制作的字典类中)。
例如,当我写时:
d["Home"] = 5;
,如果没有"Home"
密钥,它将创建一个密钥并将其值分配给5
,如果有密钥,它将其值更改为5
。
以及编写
时int i = d["Home"];
操作员将返回"Home"
键的值。
我已经尝试过使用2
类(Dict and Node
)来做到这一点,但是我不明白为什么代码无法编译并且无法正常工作。
这是Dict标头:
#include <iostream>
#include <vector>
#include "Node.h"
using namespace std;
template <class K, class V>
class Dict {
protected:
vector<K> keys;
vector<Node<V>> values;
public:
Dict();
V& operator[](const K &str);
};
这是Dict cpp:
#include "Dict.h"
template <class K, class V>
Dict<K,V>::Dict() {};
template <typename K, typename V>
V& Dict<K,V>::operator[](const K &str) {
V lol;
for(int i = 0; i < this->keys.size(); i++){
if(this->keys[i] == str){
Node<V> n = this->values[i];
return n.value;
}
}
this->keys.push_back(str);
return lol;
}
template class Dict<string, int>;
这是Node标头:
#include <iostream>
#include <vector>
using namespace std;
template <class V>
class Node {
protected:
Node& operator=(const V& val);
public:
V value;
};
这是节点cpp:
#include "Node.h"
template <typename V>
Node<V>& Node<V>::operator=(const V &dict) {
this->value = dict;
return *this;
}
这是主要内容:
int main() {
Dict<string, int> d;
d["Home"] = 6;
cout << d["Home"] << endl;
cout << "Home2" << endl;
return 0;
}
答案 0 :(得分:2)
return lol;
您返回对临时目录的引用。 lol
在}
被摧毁
未找到str
时,还需要在值中插入默认的Node<V>
。
template <typename K, typename V>
V& Dict<K,V>::operator[](const K &str)
{
for(int i = 0; i < this->keys.size(); i++)
{
if(this->keys[i] == str)
{
// Found, return corresponding value by reference.
return this->values[i].value;
}
}
// Not found, Insert into keys and values.
this->keys.push_back(str);
this->values.push_back(Node<V>()); //this will insert a default corresponding value in values.
return this->values.back().value; //this will return reference to the recently added value node
}
答案 1 :(得分:0)
我认为您在这里使事情变得过于复杂了。
首先,正如Yksisarvinen在上面的评论中已经提到的那样,您正在翻译单元中定义模板化类,这仅在某些情况下才是可能的。 Yksisarvinen发布的链接对此进行了很好的解释。
第二,正如Gaurav注意到的那样,您正在从函数返回一个临时变量,并且由于您说过代码已编译,我怀疑您是在抑制编译器警告,这不是最佳实践,因为它会导致令人讨厌的错误
无论如何,对于创建字典的问题,只使用一个存储容器存储键和值就可以了。然后,当您想使用某个键访问值时,可以遍历容器,查看键是否已经存在,如果存在,则返回值,如果不存在,则使用默认构造的值插入键并返回
它可以很简单(Dict.h):
#include <vector>
#include <algorithm>
using namespace std;
template <class TKey, class TValue>
class Dict {
struct KeyValue {
TKey key;
TValue value;
KeyValue(TKey key, TValue value)
: key(move(key))
, value(move(value)) {}
};
vector<KeyValue> pairs;
public:
Dict() = default;
TValue& operator[](const TKey &key) {
auto match = find_if(pairs.begin(), pairs.end(),
[&key](const KeyValue& pair) { return pair.key == key; }
);
if (match != pairs.end()) {
return match->value;
}
pairs.emplace_back(key, TValue());
return pairs.back().value;
}
};
我在您的代码中看到的另一个坏习惯不是使用名称空间作用域解析运算符,而是使用该using namespace std;
语句污染了全局名称空间。如果您开始使用更多的库并通常在更大的代码库上工作,那么这可能会给您带来极大的打击。