如何一起使用operator +和operator =?

时间:2013-04-22 08:17:40

标签: c++ operators redefinition

我班上有2名操作员有点问题。

我的班级被宣布:

template <class keyType, class valueType>
class MyMap{

    keyType keys[MAX];
    valueType values[MAX];
    int size;
}

我需要重新定义operator [],例如当我打电话: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类型。

我该怎么办?

5 个答案:

答案 0 :(得分:2)

问题本身并不是输出;这是你做什么的时候 钥匙不存在。我认为你指定是非常重要的 在走得更远之前。有很多可能性:

  • 您可以执行std::map所做的操作,并使用默认值插入它 值。这在很多情况下非常方便,但确实意味着 你不能在const地图上使用[]

  • 您可以让操作符返回一个指针,返回null 如果对象不存在则指针。就个人而言,我不喜欢 这适用于operator[];这意味着你必须写东西 比如:ValueType* p = myMap[ key ]; if ( p != NULL ) ...,哪个 []似乎并不自然。 (另一方面,它确实有效 以及findget函数。)

  • 你可以抛出一个异常(如果你的话,甚至可以使用一个断言) 提供contains函数,并将其作为前提条件 [])。

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

  • 最后(这似乎是你的目标):你 可以让operator[]返回代理,以便取消 用作右值的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 );
    }
};

答案 1 :(得分:1)

“但在我的算子[]中,我增加了尺寸参数”。

别。检查密钥是否存在,仅在插入新密钥时才递增size。当你正在做std::cout时,大概你只是在现有的键/值对上这样做。

[编辑] 鉴于评论,这是一个替代解决方案。在operator[]中,返回MyMap<KeyType, ValueType>::proxy。这包裹了MyMap&Key。重载MyMap::proxy::operator=(ValueType)以分配新值,并增加size。重载MyMap::proxy::operator ValueType() const以获取值。如果密钥不存在,则返回ValueType()

答案 2 :(得分:1)

当你写:

auto blah = map[key];

使用key调用operator [],并返回一个值。

当你写:

map[key] = blah;

然后使用key调用operator [key],并返回一个值,然后使用blah参数调用operator =。

这意味着可能很难检测到您实际在何处阅读或写入地图。

然而,通常情况下,在READ情况下​​,案例可能会回落到被调用的value const& operator[] const,而在写入过程中,它会是value& operator[] 而没有const 标记。因此,可能尝试通过const说明符重载运算符:提供2个运算符[] s,一个const,一个非const,并仅在后者中增加大小。

这很简单,但并不总能正常运行,因为您可能会在某个时候意外地将'operator []视为'read',但是编译器在此时无法确定const约束。我现在无法确切地说出何时以及如何以及是否有可能,但我想如果你对const不是很谨慎,你可以很容易地打出它。

如果你点击它,那么我所知道的唯一选择是在非const模式下为返回值提供一个包装器,并为const模式保持正常:

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

你的包装将会记得一个参考和到你的Map并woudl记住KEY,那个包装器将提供一个隐式转换-TO-valueType,它将提供一个分配运算符FROM-valueType-TO-wrappertype。隐式转换为值类型woudl执行read-from-map-from-given-key并且不会增加te计数器,而operator =(from-valuetype,to-wrappertype)将执行对映射的写入。

这肯定会奏效,但这种方法可能会过时。我不熟悉c'11的变化,所以现在可能有一些更好的选项 - 例如,移动&&语义可能会在这里改变一些东西,即可能是重载

 valueType&& operator[](key)

也是可能的----但我不知道。我只知道return-a-transparent-wrapper方法。

编辑:这是一个很好的(似乎完整的)适当的operator []重载示例,它支持读取和写入,并区分这两者:

stack: How to do some stuff with values assigned in subscript operator?

答案 3 :(得分:1)

如果要区分读写操作,解决方案是从operator []返回代理对象。

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

答案 4 :(得分:0)

仅当size中不存在key时,您才会增加keys,对吗?这就是std::map的作用。因此,如果您只是打印地图的内容,您将读取现有密钥的值,因此size将不会增加。