有没有办法从中制作更抽象的代码?

时间:2014-12-10 10:43:11

标签: c++

我有以下问题:我有一个Data类,它在一个向量中存储字符串,以及从它派生的两个类:Team和Player。我想制作一个索引表,以便用一个存储与字符串相关的整数的映射来表示,例如。播放器的ID存储在向量的第0个位置。这是代码(不详细):

class Data{
protected:
    std::vector<std::string> data;
    //etc.
};

class Player:public Data{
    static std::map<std::string, int> table_of_indices;
public:
    std::string operator[](const std::string& str) {return data[table_of_indices[str]];}
};

class Team:public Data{
    static std::map<std::string, int> table_of_indices;
public:
    std::string operator[](const std::string& str) {return data[table_of_indices[str]];}
};

问题在于两个派生类看起来完全相同,因为它们的地图内容是不同的。但是,有没有办法在某种程度上包含元素访问运算符和Data类中的索引表,然后分别初始化Player和Team类的映射?

2 个答案:

答案 0 :(得分:4)

首先,这不是一个好的客观编程。你应该问自己一个问题:&#34;玩家是数据吗?&#34;和#34;团队是数据吗?&#34;。答案是否定的,因此玩家和团队不应该来自Data

您应该使用此附加元素扩展您的Data类,然后在PlayerTeam中使用它。

您的新Data课程应类似于:

class Data{
    std::vector<std::string> data;
    std::map<std::string, int> table_of indices;
    //etc.
    public:
        std::string operator[](const std::string& str) {return data[table_of_indices[str]];}
};

然后,您可以使用不同的map初始化它以用于不同的用途。

为了避免克隆整个map,您可以使用指针代替map:

std::map<std::string, int>* table_of indices;

然后在Data构造函数中,您可以设置指针:

public Data(std::map<std::string, int>* table_of_indices) {
    this.table_of indices = table_of_indices;
}

现在在Player内你仍然可以拥有静态地图。另外,您应该添加Data实例。

class Player {
       static std::map<std::string, int> table_of indices;
       Data *player_data;
   public:
       std::string operator[](const std::string& str) {return *player_data[str];}
       Player() { player_data = new Data(&Player::table_of_indices); }
       ~Player() { delete player_data; }
};

答案 1 :(得分:3)

这是CRTP的工作!

template <class Tderived>
struct DataIndexer : Data {
    friend struct Tderived;

    std::string const &operator [] (const std::string& str) const {
        return data[table_of_indices[str]];
    }

private:
    DataIndexer() {}

    static std::map<std::string, int> table_of_indices;
};

现在,您可以从Player继承DataIndexer<Player>,并且新的实例将拥有自己的静态成员。