如何将运算符+和运算符=一起使用
How to use operator+ and operator= together?
我的类中有两个运算符有点问题。
我的班级被宣布为:
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 ) ...
对于[]
来说似乎并不自然。(另一方面,它确实有效具有find
或get
功能( -
如果您提供
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
不会递增。
- 为什么常量词在重载运算符中不与 ostream 对象一起使用<<?
- 将 [][] 运算符与向量一起使用?
- 不能将重载比较运算符与 Catch 测试一起使用
- 让类与运算符一起工作更简单的方法
- #define 与运算符一起使用
- 是否可以将引用类型别名与指针运算符一起使用来声明对指针的引用?
- 返回对象如何与分配运算符一起工作
- 将逻辑 OR 与 cout 运算符一起使用
- 为什么在 sizeof() 函数中与 * 运算符一起使用和不使用 * 运算符时,指向结构变量的指针大小会有所不同?
- 我可以将 std:fixed 或 std::setprecision() 与>>运算符一起使用吗?
- 如何使 QList<Type*> 与 indexOf() 和自定义运算符==()一起使用?
- 将 std::forward 与 typeid 运算符一起使用是否有意义
- 如何将 std::<list>::reverse_iterator 与运算符 + 一起使用?
- 与类型转换运算符一起使用时条件运算符"?:"的编译器错误
- 如何将运算符[]与运算符=一起使用
- 与条件运算符一起使用时,动作不一致
- 我可以将enable_if之类的东西与隐式转换运算符一起使用吗
- 如何将运算符+和运算符=一起使用
- C++如何验证输入以与重载>>运算符一起使用
- 如何使用 std::find 与不是 std::less 的<运算符一起使用