【问题标题】:c++ std::map class with generic keyc++ std::map 具有通用键的类
【发布时间】:2016-11-01 22:53:45
【问题描述】:

我有一个类族,每个子类都需要一个映射,但是键将具有不同的类型,尽管它们都将对映射执行完全相同的操作。两种情况下的值也都是字符串。 到目前为止,我的代码类似于下面的示例,我的目标是重用代码,通过 有一个通用键。 除了 STL 之外,不使用任何其他库

class A{
 public:
    /*
     * More code
     */
};


class subA1 : public A{
public:
    void insertValue(long id, std::string& value){
        if(_theMap.find(id) == _theMap.end())
        {
            _theMap[id] = value;
        }
    }

 private:
     std::map<long,std:string> _theMap;
};

class subA2 : public A{
public:
    void insertValue(std::string& id, std::string& value){
        if(_theMap.find(id) == _theMap.end())
        {
            _theMap[id] = value;
        }
    }
private:
     std::map<std::string,std:string> _theMap;

};

【问题讨论】:

  • 你是什么意思通用密钥?另一个模板? std::variant?
  • 子类之间除了地图类型不同,还有其他区别吗?
  • balki:两个子类执行非常不同的操作,但地图中数据的存储和检索是相同的,还有一些共同的代码
  • @ulitosCoder 在这种情况下,这个解决方案应该可以工作:stackoverflow.com/a/40370038/463758

标签: c++ generics stl stdmap


【解决方案1】:

只需将超类 A 设为模板,将 _theMap 和 insertValue() 都移至其中,并在子类中使用正确的模板版本。

template <typename KeyT>
class A{
 public:
   void insertValue(KeyT id, std::string& value){
        if(_theMap.find(id) == _theMap.end())
        {
            _theMap[id] = value;
        }
    }

 private:
     std::map<KeyT, std:string> _theMap;
};

class subA1 : public A<long> {};

class subA2 : public A<std::string> {};

【讨论】:

  • 根据A、subA1 和subA2 之间的实际关系,将subA1 和subA2 合并到一个执行包含map 并派生自非模板A。
  • 他在评论中说“两个子类执行非常不同的操作,但地图中数据的存储和检索是相同的”。
【解决方案2】:

您可以将subA1 和subA2 合并到一个模板类中,例如:

class A{
 public:
    /*
     * More code
     */
};

template <typename KeyType>
class subA : public A {
public:
    void insertValue(const KeyType &id, const std::string& value) {
        if(_theMap.find(id) == _theMap.end()) {
            _theMap.insert(std::make_pair(id, value));
        }
    }

 private:
     std::map<KeyType, std:string> _theMap;
};

然后您可以根据需要创建 typedef:

typedef subA<long> subA1;
typedef subA<std::string> subA2;

或者,如果您需要实际的派生类:

class subA1 : public subA<long>
{
    ...
 };

class subA2 : public subA<std::string>
{
    ...
};

【讨论】:

  • 我认为这是一个很好的解决方案,因为我需要 A 类是抽象的,因为直到运行时我才知道要创建哪个特定的子类实例。
【解决方案3】:

编写另一个小基类怎么样,比如C&lt;T&gt;,它是一个template typename T,只包含一个map&lt;T, string&gt; 和你的insert 函数。那么 A 的每个新子类也将是 C 的子类。所以你的subA1 将是public A, public C&lt;long&gt; 等等。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-26
    • 2018-11-08
    • 2011-04-02
    • 2022-11-01
    • 1970-01-01
    • 2011-06-16
    相关资源
    最近更新 更多