簡體   English   中英

關於類和多態的疑惑

[英]Doubts about classes and polymorphism

我正在嘗試使用鏈接方法在 C++ 中構建一個 hash 表 class,最小示例 class 是:

template <class V>                                                                  
class HashTable {                                                                                                                                                                                                            
private:                                                                                                       
  //some parameters to define the hash_table                                                                                                  
  HashFunc * h;  //family of hash functions                                                                                                                                                                                                                                                          
public:                                                                                                       
  /*other functions*/                                                                       
};

我在使用成員 HashFunc HashFunc * h遇到了一些麻煩,它是 hash function 我打算用來在 hash 表中存儲對 <key,value> 。 在我的main中,我需要構建兩個不同的 hash 表,一個散列整數,另一個散列字符串。

我的疑問是:

  1. 對我來說,一個自然的選擇是通過以下方式對 hash function 使用多態(請注意,我對類和多態的經驗有限):
class HashFunc{
public:
  virtual int operator()()=0;
}
    
class IntegerHashFunc: public HashFunc
{
  //parameters to hash integers
 public:
  int operator()(int x){
    //operations for integer hashing
  }
}

class StringHashFunc: public HashFunc
{
  //parameters to hash strings
  IntegerHashFunc h_integer; //string->integer->integer hash
  public:
    int operator()(string name){
      int result=0;
      //operations for string hashing
      return h_integer(result); //I need to hash the integer resulting from string "hashing"
    }
}

但這行不通,因為 StringHashFunc 中的operator()(string name)具有不同的StringHashFunc ,因此不會覆蓋 base class 中的virtual方法。如何使它工作?

  1. 我不確定如何在HashTable class 的構造函數中進行這項工作:如何在這兩種方法之間進行選擇? 我應該只在構造函數中使用一個標志,例如:
template<class V>
HashTable<V>::HashTable(/*args*/, int flag){
  //other parameters
  switch(flag){
    case 1:
      h=new IntegerHashFunc(/*args for integer hashing*/);
    case 2:
      h=new StringHashFunc(/*args for string hashing*/);
  }
}

或者,還有更好的方法?

  1. 有沒有更好更自然的方式來做我想做的事? 例如,我嘗試使用帶有兩個重載operator()(int)operator()(string)的單個 class HashFunc ,但如果我只使用整數,我不想“攜帶”字符串參數和方法.

TL;DR - 所有問題的答案都是“使用模板,而不是多態性”。

對我來說,一個自然的選擇是通過以下方式對 hash function 使用多態(請注意,我對類和多態的經驗有限):
但這行不通,因為 StringHashFunc 中的 operator()(string name) 具有不同的 arguments,因此不會覆蓋 base class 中的虛方法。如何使它工作?

你不能。 為了使派生的class成為非抽象的,需要覆蓋所有的純虛函數。 即使您添加另一個帶參數的重載,也無濟於事,因為您無法使用基指針 class 調用這些重載。
理論上,您可以執行dynamic_cast以確定實際類型是什么(在一長串if語句中),但不鼓勵這樣做。

我不確定如何在 HashTable class 的構造函數中進行這項工作:如何在這兩種方法之間進行選擇? 我應該只在構造函數中使用一個標志,例如:
或者,還有更好的方法?

一種選擇是將類型特征用於 select 正確的分支(假設您真的非常想使用多態性):

if(std::is_same_v<V, int>) 
    h=new IntegerHashFunc(/*args for integer hashing*/);
else if(std::is_same_v<V, std::string>)
    h=new StringHashFunc(/*args for string hashing*/);

有沒有更好更自然的方式來做我想做的事? 例如,我嘗試使用帶有兩個重載 operator()(int) 和 operator()(string) 的單個 class HashFunc,但如果我只使用整數,我不想“攜帶”字符串參數和方法.

是的,使用模板,就像標准庫 hash 表(又名std::unordered_map )一樣:

template<typename T>
class HashFunc{
public:
  int operator()(const T&) const;
};

template<>
class HashFunc<int>{
public:
  int operator()(const int&) const {
    // do calculations for int
  }
};

template<>
class HashFunc<std::string>{
public:
  int operator()(const std::string&) const {
    // do calculations for std::string
  }
};

//etc... for all other specializations

template <class V>                                                                  
class HashTable {                                                                                                                                                                                                            
private:                                                                                                       
  //some parameters to define the hash_table                                                                                                  
  HashFunc<V> h;  //family of hash functions                                                                                                                                                                                                                                                          
public:                                                                                                       
  /*other functions*/                                                                       
};

或者更好的是,使用已經存在的std::hash ,它就是這樣做的,但已經實現了。

使用基於策略的設計,它會簡單得多。

首先創建您的 hash 函數對象:

struct IntegerHashFunc
{
  int operator()(int x){ return x; }
};

struct StringHashFunc
{
  IntegerHashFunc h_integer; //string->integer->integer hash
    int operator()(string name){
      int result=0;
      return h_integer(result);
    }
};

您的HashTable表 class 會將 Hash function 作為模板參數。

template <typename Key, typename Val, typename HashFunctionPolicy = IntegerHashFunc>
class HashTable {                                                                                                                                                                                                            
private:                                                                                                       
  //some parameters to define the hash_table                                                                                                                                                                                                                                                         
public:                                                                                                       
  /*other functions*/
  void somefunction(Key key)
  {
      HashFunctionPolicy f;
      auto x = f(key);
  }                                                                   
};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM