在C++; 我的目标是为我在C++模板类中写的哈希表实现一个Rhhash()方法。然而,我不知道我到底可以散列什么,因为这个方法只知道类型是泛型。据我所知,这与Java泛型不同

在C++; 我的目标是为我在C++模板类中写的哈希表实现一个Rhhash()方法。然而,我不知道我到底可以散列什么,因为这个方法只知道类型是泛型。据我所知,这与Java泛型不同,c++,hashtable,C++,Hashtable,我对java的理解。。。 在Java中,由于每个对象都继承hashCode()方法,因此我们可以重写此方法。如果用java编写通用哈希表,那么在rehash()期间,可以简单地调用hashCode()方法以返回值。它可以通过表大小进行修改。无痛 回到C++… 由于我不相信我可以简单地调用一个HASCODE()方法来访问C++泛型,也不需要访问泛型类型的数据成员,所以我不知道我可以重新定义什么。 < P> >我的泛型类型是否可能在C++中继承一个抽象类,因此我可以强制使用一个虚拟HASCODE()

我对java的理解。。。 在Java中,由于每个对象都继承hashCode()方法,因此我们可以重写此方法。如果用java编写通用哈希表,那么在rehash()期间,可以简单地调用hashCode()方法以返回值。它可以通过表大小进行修改。无痛

回到C++… 由于我不相信我可以简单地调用一个HASCODE()方法来访问C++泛型,也不需要访问泛型类型的数据成员,所以我不知道我可以重新定义什么。 < P> >我的泛型类型是否可能在C++中继承一个抽象类,因此我可以强制使用一个虚拟HASCODE()= 0方法? 或者模板类中的散列函数是否依赖于某种其他类型的非datamember散列


尽量说清楚。感谢所有能为我指出正确方向或提供指导的人。

注意:当然,我想您实现哈希表的目的是为了学习。如果没有,请使用
std::unordered_map

这里最重要的一点是您已经注意到的:模板和泛型不是一回事。(由于类型擦除,java泛型只是一种奇特的语法糖工具,但这是另一回事)

C++模板可以为模板的每个不同实例编写一个类的版本。也就是说,如果在您的程序中使用
std::vector
std::vector
,编译器将为类型为int的类向量和类型为bool的类向量生成代码

模板最强大的方面之一是在编译时对每个类型相关的操作进行评估。也就是说,每个模板实例、别名、typedef等都是在编译时完成的。运行时获得的代码是为不同模板实例最终生成的类的组合。因此,您不会在运行时考虑类型,就像在java或C#等OO语言中一样,而是考虑编译时编译结束时必须解决所有问题

现在我们来看看您的问题:
您希望为您的类型提供一个“可哈希”接口,以调用哈希表中的哈希函数。 这可以通过两种方式实现:

基于成员功能的方式: 解决问题的一种方法是假设您的类型有一个
hash()
公共成员函数(如java中的
getHashCode()
,它是从对象继承的)。 因此,在hashtable实现中,使用这个hash函数就像元素拥有它一样。不要担心传递的类型。 事实上,如果您这样做,并且您传递了一个没有公共哈希成员函数的类型作为模板参数,那么该模板将无法实例化。维奥拉
将模板视为契约:在模板中编写完全通用的代码。传递给模板的类型必须完全填充合同。也就是说,必须拥有你认为他们拥有的一切

这种方法的问题是hashmap中使用的任何类型都必须具有hash public成员函数。注意,通过这种方式,您不能在hashmap中使用基本类型

基于函子的方法: 函子是充当函数的类。也就是说,该类的实例可以作为函数使用。例如:

template<typename T>
struct add
{
    T operator()(const T& a , const T& b)
    {
        return a + b;
    }
};
class my_search_criteria
{
   bool operator()(int element)
   {
      return element == 0;
   }
};  

int main()
{
    std::vector<int> integers = { 5 , 4 , 3 , 2 , 1 , 0 };

    int search_result = std::find_if( std::begin( integers ) , std::end( integers ) , my_search_criteria() );
}
但是,函子如何帮助解决您的问题呢?
可以实现充当哈希函数的泛型函子:

template<typename T>
struct hash
{
   unsigned int operator()(const T& element) 
   {
      return /* hash implementation */
   }
};
我们需要为您将在hashmap中使用的每种类型专门化。例如,无符号整数的专门化:

template<>
struct hash<unsigned int>
{
   unsigned int operator()(unsigned int element)
   {
       return element;
   }
};
模板
结构散列
{
无符号整数运算符()(无符号整数元素)
{
返回元素;
}
};

基于函件的方式正是C++标准库所做的。它有一个哈希函子的定义,并在哈希表实现中使用它,如。请注意,库中有一组用于基本类型的内置哈希专门化。

注意:当然,我认为实现哈希表的目标是为了学习。如果没有,请使用
std::unordered_map

这里最重要的一点是您已经注意到的:模板和泛型不是一回事。(由于类型擦除,java泛型只是一种奇特的语法糖工具,但这是另一回事)

C++模板可以为模板的每个不同实例编写一个类的版本。也就是说,如果在您的程序中使用
std::vector
std::vector
,编译器将为类型为int的类向量和类型为bool的类向量生成代码

模板最强大的方面之一是在编译时对每个类型相关的操作进行评估。也就是说,每个模板实例、别名、typedef等都是在编译时完成的。运行时获得的代码是为不同模板实例最终生成的类的组合。因此,您不会在运行时考虑类型,就像在java或C#等OO语言中一样,而是考虑编译时编译结束时必须解决所有问题

现在我们来看看您的问题:
您希望为您的类型提供一个“可哈希”接口,以调用哈希表中的哈希函数。 这可以通过两种方式实现:

基于成员功能的方式: 解决问题的一种方法是假设您的类型有一个
hash()
公共成员函数(如java中的
getHashCode()
,它是从对象继承的)。 因此,在hashtable实现中,使用这个hash函数就像元素拥有它一样。不要担心传递的类型。 事实上,如果您这样做,并将类型作为模板传递
template<typename T>
class hachtable
{
private:
   hash<T> hash_function;
   std::vector<T> _container;

   void add(const T& element)
   {
      _container.insert(std::begin( _container ) + hash_function( element ) , element);
   }
};
template<typename T>
struct hash;
template<>
struct hash<unsigned int>
{
   unsigned int operator()(unsigned int element)
   {
       return element;
   }
};