如何将运算符+和运算符=一起使用

How to use operator+ and operator= together?

本文关键字:运算符 一起      更新时间:2023-10-16

我的类中有两个运算符有点问题。

我的班级被宣布为:

template <class keyType, class valueType>
class MyMap{
    keyType keys[MAX];
    valueType values[MAX];
    int size;
}

我需要重新定义运算符[],例如当我调用:std::cout<<MyMap1["a"];时。

keyType& operator[] (keyType key){}

它运行良好。我也用它来做作业,它很好,例如:MyMap1["a"]="a1";

代码非常完美。但在我的operator[]中,我增加了size参数,只有当我想进行赋值时,它才有用。当我只做std::cout时,我不想增加它。

所以也许我应该重新定义operator=函数,但当我不能写的时候:

void operator=(valueType value){}

因为MyMap1["a"] = "a1"的左边成员是keyType而不是MyMap类型。

我该怎么办?

问题本身不是输出;当密钥不存在。我认为你具体说明是非常重要的再往前走。有很多可能性:

  • 您可以执行std::map的操作,并使用默认值插入价值这在很多情况下都很方便,但它确实意味着不能在常量映射上使用[]

  • 您可以让运算符返回一个指针,其中包含一个null指针(如果对象不存在(。就我个人而言,我不喜欢这是针对CCD_ 12;这意味着你必须写东西如:ValueType* p = myMap[ key ]; if ( p != NULL ) ...对于[]来说似乎并不自然。(另一方面,它确实有效具有findget功能(

  • 如果您提供contains功能,并将其作为[](。

  • 您可以返回预定义的默认值。这有点像与第一种解决方案相反;意味着operator[]永远不会改变地图,也不需要非常量版本。

  • 最后(这似乎就是你的目标(:你可以让operator[]返回一个代理,以便distiguish在用作右值的myMap["a"]myMap["a"] = something之间。我的感觉是,这个解决方案不适合很好地理解C++的工作方式,但它也用于其他语言(例如,类似Python(。

对于最后一个解决方案,您可以使用以下内容:

class MyMap
{
    class Proxy
    {
        MyMap* myOwner;
        KeyType myKey;
    public:
        Proxy( MyMap* owner, KeyType key )
            : myOwner( owner )
            , myKey( key )
        {
        }
        Proxy const& operator=( ValueType value ) const
        {
            myOwner->insertOrUpdate( myKey, value );
            return *this;
        }
        operator ValueType() const
        {
            if ( !myOwner->contains( myKey ) ) {
                throw UnknownKeyException( myKey );
            }
            return myOwner->get( myKey );
        }
    };
public:
    Proxy operator[]( KeyType key )
    {
        return Proxy( this, key );
    }
};

如果您想区分读取和写入操作,解决方案是从operator []返回一个代理对象。

有关示例,请参见https://stackoverflow.com/a/16132858/320726

"但在我的运算符[]中,我增加了大小参数"。

不要。检查密钥是否存在,只有在插入新密钥时才递增size。当您执行std::cout时,可能只在现有的键/值对上执行。

[编辑]根据评论,这里有一个替代解决方案。在operator[]中,返回一个MyMap<KeyType, ValueType>::proxy。这将封装一个MyMap&Key。重载MyMap::proxy::operator=(ValueType)以分配新值,并递增size。重载MyMap::proxy::operator ValueType() const以获取值。如果密钥不存在,则返回ValueType()

编写时:

auto blah = map[key];

使用key调用运算符[]并返回一个值。

当你写:

map[key] = blah;

然后使用key调用运算符[key],并返回一个值,然后对具有blah参数的值调用运算符=。

这意味着可能很难检测到你实际在地图上读或写的地方。

但是,通常情况下,在READ的情况下,情况可能会回落到调用的value const& operator[] const,而在写入期间,它将是不带const标记的value& operator[]。因此,可能会尝试通过常量说明符重载运算符:提供2个运算符[]、一个常量、一个非常量,并仅在后者中增加大小。

这是一个简单但并不总是能正常工作,因为您可能会在某个时候意外地调用"operator[]as read",但此时编译器无法确定常量约束。我目前还不能确切地说什么时候、如何以及是否有可能做到这一点,但我想,如果你不小心,你会很容易做到的。

如果你达到了这一点,那么我所知道的唯一选项就是为非常量模式下的返回值提供一个包装器,并为常量模式保留正常:

myMap::valueType const & operator[](key...) const
mymap::wrapper<myMap::valueType>& operator[](key...)

你的包装会记住一个ref&请记住KEY和该包装器将提供一个隐式的转换到valueType,并提供一个赋值运算符FROM valueType到wrappertype。对valuetype的隐式转换将在给定的键下执行从映射的读取,并且不会递增计数器,而运算符=(从valuetype到wrappertype(将执行对映射的写入。。

这肯定会奏效,但这种方法可能已经过时了。我对c'11的更改不太熟悉,所以现在可能有一些更好的选项可用——例如,move &&语义可能会改变这里的某些内容,即可能是过载

 valueType&& operator[](key)

也有可能----但是我不知道。我只知道返回-透明-包装方法。

编辑:这里有一个很好的(似乎完整的(例子,说明了一个适当的运算符[]重载,它既支持读写,又区分这两者:

stack:如何使用下标运算符中指定的值做一些事情?

只有当keys中不存在key时,您才会增加size,对吗?std::map就是这么做的。因此,如果您只是打印地图的内容,您将读取现有关键点的值,因此size不会递增。