我正在编写一种类框架,我需要获取对象的哈希值,以便将它们存储在哈希表中。
如果我有:
class A {
int a;
};
class B : public A {
const char* str;
};
class C : public A {
double d;
otherClass* oc;
};
我需要能够通过散列函数运行B
或C
来获取对象的散列。
我应该怎么做?我只想做sizeof(thing)
并对原始字节进行哈希处理,但这是一个很好的方法吗?我还想过在基类中有virtual uint_32 hash() = 0
,但是对于每个子类都必须实现它是不是最理想的。
答案 0 :(得分:2)
通常,您需要使用哈希函数与类中定义的相等性保持一致。可能等于由重载operator==
定义,但即使没有重载,您可能会认为两个对象应该被认为是相同的,并且如果它们的所有数据成员相等,则具有相同的哈希码。
散列原始字节通常不起作用。无法保证数据成员全部相等的两个对象具有相等的字节。例如,对象可能在某处有一些填充,出于对齐的原因,填充字节可以取任何值。
更糟糕的是,无法保证两个相等的double
值具有相等的字节。例如,正/负零比较相等。
C的情况特别棘手:如果两个C对象指向不同的otherClass
对象,但两个otherClass
对象相等,那么两个C对象是否应该具有相同的哈希值?你无法完全概括地定义它,它是C类的属性。
如果它也是最好的可能,那么某些事情可能是“次优的”吗? ;-)唯一的通用解决方案是定义函数hash
,并为每个类编写一个版本。在你的情况下,你可能会使它成为A的虚函数,但你也可以看看std::hash
在C ++ 0x中是如何工作的:它实际上是一个模板函子类而不是函数,它可以专门用于用户 - 定义的类。当然,这并不提供动态多态性,但是如果你专门为A
,并让实现调用一个虚函数,你在每个类中实现,那么你的哈希函数将与{{1}一起使用等等。
答案 1 :(得分:1)
如果对象具有未初始化的字段(对象具有不同的无意义位)或动态成员(对象具有不同的指针,即使它们指向对象),执行sizeof
事物可以为您提供相同对象的不同哈希值相同的数据)。你不能比编写一个序列化器好,然后通过你的哈希函数运行结果。
至于为每个基类实施hash()
的成本,您有三种选择。
我建议从2开始,然后转到3个零碎。