简体   繁体   English

多个任务的运算符重载下标和赋值运算符

[英]Operator Overloading subscript and assignment operator for multiple tasks

I want to overload the operator [] and = for multiple tasks (in a dictionary class that I made). 我想为多个任务(在我制作的字典类中)重载运算符[]=

when I write for example: 当我写例如:

d["Home"] = 5;

and if there is no "Home" key, it will create a key and assign the value to 5 , and if there is the key, it will change its value to 5 . 如果没有"Home"键,它将创建一个键并将其值分配为5 ;如果有该键,则它将其值更改为5

and also, when writing 而且,当写作时

int i = d["Home"];

the operator will return the value of the "Home" key. 操作员将返回"Home"键的值。 I have tried to do that with 2 classes ( Dict and Node ) but I can't understand why the code doesn't compile and it's not working. 我尝试使用2类( Dict and Node )来做到这一点,但我不明白为什么代码无法编译且无法正常工作。


this is the Dict header: 这是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);
};

this is the Dict cpp: 这是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>;

this is the Node header: 这是Node标头:

#include <iostream>
#include <vector>
using namespace std;


template <class V>
class Node {
protected:
    Node& operator=(const V& val);
public:
    V value;
};

this is the node cpp: 这是节点cpp:

#include "Node.h"
template <typename  V>
Node<V>& Node<V>::operator=(const V &dict) {
    this->value = dict;
    return *this;

}

and this is the main: 这是主要的:

int main() {
    Dict<string, int> d;

    d["Home"] = 6;
    cout << d["Home"] << endl;
    cout << "Home2" << endl;
    return 0;
}
return lol;

You return a reference to a temporary. 您返回对临时的引用。 lol gets destroyed at } lol}被摧毁

When str is not found, you also need to insert a default Node<V> in values. 当找不到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 
}

See code in action 查看实际代码

I think you are overcomplicating things here a bit. 我认为您在这里使事情变得过于复杂。

First of all, as Yksisarvinen has already mentioned in the comment above, you are defining a templated class in a translation unit which is only possible under certain circumstances. 首先,正如Yksisarvinen在上面的评论中已经提到的那样,您正在翻译单元中定义模板化类,这仅在某些情况下才是可能的。 It's explained fairly well in the link Yksisarvinen has posted. Yksisarvinen发布的链接中对此进行了很好的解释。

Second, as Gaurav has noticed, you are returning a temporary from a function and since you said that your code compiles, I suspect you are suppressing the compiler warnings, which isn't the best practice, as it leads to nasty bugs. 其次,正如Gaurav所注意到的那样,您正在从函数返回一个临时变量,并且由于您说过代码已编译,因此我怀疑您是在抑制编译器警告,这不是最佳实践,因为它会导致令人讨厌的错误。

Anyway, to your question of creating a dictionary, you should be just fine with using only one storage container for the keys and values. 无论如何,对于创建字典的问题,只使用一个存储容器存储键和值就可以了。 Then, when you want to access the value using some key, you can go through the container and look if the key already exists, if it does, return the value, if not, insert the key with a default-constructed value and return it. 然后,当您想使用某个键访问值时,可以遍历容器,查看键是否已经存在,如果存在,则返回值,如果不存在,则使用默认构造的值插入键并返回。

It can be as simple as this (Dict.h): 可以这样简单(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;
    }
};

LIVE DEMO 现场演示


Another bad habit I can see in your code is not using namespace scope resolution operator, but rather polluting the global namespace with that using namespace std; 我在您的代码中看到的另一个坏习惯不是使用名称空间范围解析运算符,而是using namespace std;污染了全局名称using namespace std; statement. 声明。 That can hit you pretty badly if you start using more libraries and generally working on bigger codebases. 如果您开始使用更多的库并且通常在更大的代码库上工作,那么这可能会给您带来极大的打击。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM