[英]Overloading operator() for a new struct
我在c中定义了一个新struct
:
typedef struct TypedObject {
ObjectType type;
void * value;
} TypedObject;
其中ObjectType是一个枚举:
typedef enum ObjectType {
type_node,
type_int,
type_error,
} ObjectType;
我想创建一个c ++类型的TypedObject
指针,从先前的问题中我了解到,我需要重载operator()
以便在插入该集合的TypedObject
指针之间进行比较。
因此,我这样做如下:
#ifdef __cplusplus
typedef struct {
bool operator() (const TypedObject *lhs, const TypedObject *rhs){
return (lhs->type==rhs->type) && (lhs->value==rhs->value);
}
} ObjComparator;
#endif
假设我定义了一个集合:
std::set<TypedObject *, ObjComparator> mySet;
您可以假设我使用迭代器来迭代该集合。
我想将TypedObject x
插入到集合中。 我使用mySet.insert(&x)
插入其地址..但是一旦我使用mySet.find(&x)
,它就找不到x
。 进行了对operator()
的调用,但未按预期进行比较。
知道我重载operator()
的方式可能是什么问题吗? 我究竟做错了什么? 另外,是否应该重载<或==之类的其他版本的运算符?
您提供的Comparator
类应该实现顺序比较 ,以便std::set
可以使用它来构建二进制搜索树。
这意味着您的operator()
不应对称-默认情况下,它是“小于”比较。
通常, Comparator
类的operator()
应该代表您的类的严格顺序关系,因此应该
C(a,b) && C(b,c)
表示C(a,c)
C(a,b)
表示!C(b,a)
!C(a,b) && !C(b,a)
表示“ a和b相等” “平等”的最后定义是调用set::find
时std::set
使用的内容。
解决方案:虽然您当然可以提出一些可以满足上述规则的排序,但是也许可以进行一些重构。
如果您的TypedObject
具有“地址标识”(即,任何对象都仅等于其自身),则可以使用默认比较-它非常适合指针:
std::set<TypedObject *> mySet;
如果您毕竟需要比较成员,则通常的方法是这样的:
bool operator() (const TypedObject *lhs, const TypedObject *rhs)
{
if(lhs->value < rhs->value) return true;
if(rhs->value < lhs->value) return false;
return (lhs->type < rhs->type)
}
请注意,它仅取决于成员的operator<
。 实际上,最好定义operator<
来比较TypedObject
,然后从指针Comparator
调用它。
最后,如果您的设备set
拥有对象(即对象在离开设备集时被销毁),那么最好使用
std::set<TypedObject> mySet;
使用operator<
对TypedObject
重载。 您仍然可以从集合中获取指向对象的指针,并在您的C API中使用它们,并且您无需处理额外的比较器类和内存管理。
您的订单比较是错误的,因为基于相等性,它将无法创建BST,因此正确的代码应如下所示(比较器中的<注意)
typedef enum ObjectType {
type_node,
type_int,
type_error,
} ObjectType;
typedef struct {
ObjectType type;
void * value;
} TypedObject;
typedef struct {
bool operator() (const TypedObject *lhs, const TypedObject *rhs){
return (lhs->type==rhs->type) && (lhs->value<rhs->value);
}
} ObjComparator;
int main()
{
std::set<TypedObject *, ObjComparator> mySet;
TypedObject obj;
obj.type=type_int;
obj.value=(void*)new int;
//*(obj.value)=4;
auto insert = mySet.insert(&obj);
std::cout<<insert.second<<std::endl;
if(mySet.find(&obj) == mySet.end())
{
std::cout<<"Not Found..."<<std::endl;
}
else
{
std::cout<<"Found..."<<std::endl;
}
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.