[英]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 表,一個散列整數,另一個散列字符串。
我的疑問是:
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
方法。如何使它工作?
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*/);
}
}
或者,還有更好的方法?
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.