2

我首先定义

class Hash
{

};

然后是哈希的专业化。

template <class T>
class Hash<int, T>
{
public:
    Hash(int slotN = 11);

    bool insert(int key, T val);
    bool remove(int key);
    bool contains(int key);
    bool query(int key, T& val) ;

protected:
    // Basic Variables of the Hash Model.
    list<int>* slot;
    list<T>* slotVal;
    int slotN;
};

我想使用这个专门版本的 Hash 来实现另一个专门化:字符串值键的哈希。

template <class T>
class Hash<string, T> : public Hash<int, T>
{
public:
    Hash(int slotN);

    bool insert(string key, T val);
    bool remove(string key);
    bool contains(string key);
    bool query(string key, T& val) ;

private:

    // Calculate the String's Hash Key.
    int str2key( string key);
};

但似乎我无法访问类 Hash 中的字段。为什么?

4

1 回答 1

2

当您说“我无法访问类 Hash 中的字段”时,我猜您的意思是,当您使用Hash<string, T>(对于某些类型T)时,您无法从Hash<int, T>. 这样做的原因是名称隐藏:当您在派生类中重载成员函数时,基类中具有相同名称的所有成员都将被隐藏,除非您使它们显式可用。这样做的方法是using声明:

template <class T>
class Hash<string, T> : public Hash<int, T>
{
public:
    Hash(int slotN);

    using Hash<int, T>::insert;
    using Hash<int, T>::remove;
    using Hash<int, T>::contains;
    using Hash<int, T>::query;

    bool insert(string key, T val);
    bool remove(string key);
    bool contains(string key);
    bool query(string key, T& val) ;

private:

    // Calculate the String's Hash Key.
    int str2key( string key);
};

如果您只需要从派生类的实现中访问基类成员,您还可以使用带有类名的限定来访问名称。例如:

template <typename T>
bool Hash<string, T>::insert(string key, T val) {
    return this->Hash<int, T>::insert(this->str2key(key, val);
}

稍微考虑一下这个问题,还有另一个潜在的问题:如果您访问基类中的数据成员,您需要确保编译器将名称视为依赖名称。否则,它会在第一阶段查找并且不会在基础中查找名称,因为只能在第二阶段找到:

template <typename T>
bool Hash<string, T>::insert(string key, T val) {
    int n0 = slotN; // doesn't work: looked up in phase 1
    int n1 = this->slotN; // OK: name is dependent
    int n2 = Hash<int, T>::slotN; // OK, too
}

就个人而言,我不会公开从具有不同密钥的类派生,但我认为你有你的理由。顺便说一句,我假设您的主要声明Hash看起来像这样,尽管这对问题无关紧要,真的:

template <typename K, typename T>
class Hash;

(如果它没有任何成员,我也不想定义它)。

于 2012-11-17T16:03:36.800 回答