重载operator()以获取新结构

时间:2017-04-17 09:15:12

标签: c++ struct compare overloading operator-keyword

我在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()的方式可能带来什么问题?我究竟做错了什么? 此外,我应该重载不同版本的运算符,如&lt;或==?

2 个答案:

答案 0 :(得分:1)

您提供的Comparator类应实施订单比较,以便std::set可以使用它来构建二进制搜索树。

这意味着您的operator()不应该是对称的 - 默认情况下它是&#34;小于&#34;比较。

一般来说,operator()类的Comparator应代表您班级的严格顺序关系,因此它应该是

  • 及物 - C(a,b) && C(b,c)表示C(a,c)
  • 反对称 - C(a,b)表示!C(b,a)
  • 总计 - !C(a,b) && !C(b,a)表示&#34; a和b相等&#34;

&#34;平等的最后定义&#34;是std::set在您致电set::find时使用的内容。

解决方案虽然您确实可以提出一些符合上述规则的排序,但也许您可以使用一些重构。

如果您的TypedObject拥有&#34;地址标识&#34; (即任何对象只等于它自己),那么你可以使用默认比较 - 它适用于指针:

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中使用它们,并且您不需要处理额外的比较器类和内存管理。

答案 1 :(得分:0)

您的订单比较是错误的,因为基于相等性它将无法创建BST,因此正确的代码应如下所示(注意&lt;在比较器中)

private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
    SqlConnection sqlcon1 = new SqlConnection(@"Data Source=PRATHISTA;Initial Catalog=CRMT;Integrated Security=True");
    sqlcon1.Open();
    SqlCommand cmd1 = new SqlCommand("select * from Requirement", sqlcon1);
    try
    {
        SqlDataReader sda1 = cmd1.ExecuteReader();
        while (sda1.Read())
        {
            string sId = sda1.GetString("Requirement_Id");
            // i get the error here;
        }
        sda1.Close();
        sqlcon1.Close();
    }
    catch (Exception ex)
    {
        MessageBox.Show("Error:" + ex);

    }
}