[List / Vector]:需要一些基础建议

时间:2014-01-28 14:43:28

标签: c++

我想就如何解决我遇到的一个有趣问题提出一些建议。

问题是有两个存储容器,用户可以选择哪个存储容器用于程序的其余部分(编辑:在运行时)。这两个容器是Vector和List,并存储我们要定义的对象类型。可以使用您想要的任何方式访问这两个容器(pop / [i] / ...)您将如何解决此问题?

以下是我最好的(几乎正常工作)解决方案,但我真的很想看看更熟练的C ++专业人士有哪些解决方案。如前所述,如果我采取正确的方法,我真的很感兴趣。这个学期我有超过典型的空闲时间,我打算用它来真正提高我的c ++能力。感谢您的反馈。

版本1

首先,我有一个布尔标志,

bool using_vector = true;   // what storage container was selected?

其次是我的两个容器,

list<Question> q_llist;
vector<Question> q_vec;

我访问容器的第三个实现, (仍然没有想出如何使get_question()以优雅的方式运作,而且我不喜欢我目前正在采取的当前路线)

const Question& get_question(){
    Question q = (using_vector) ?
            q_vec.back() : q_llist.back();

    (using_vector) ?
            q_vec.pop_back() : q_llist.pop_back();

    return q;
}


int questions_size(){
    return (using_vector) ?
            q_vec.size() : q_llist.size();
}


void push_back_question(Question& q){
    if(using_vector){
        q_vec.push_back(q);
    }else{
        q_llist.push_back(q);
    }
}

版本2

注意:请使用标签&#34;#v2&#34;在引用时。

我决定尝试多态方法。这个实现看起来如何?

/**
 * using polymorphism to implement a parent class "Container"
 * depending on user selection, reference C_Vec or C_List
 */
class Container {
protected:
    list<Question> qlist;
    vector<Question> qvec;

public:
    void push_back(Question& q){/** do nothing */}
    void pop_back(){/** do nothing */}
    int size(){/** do nothing */}
    Question& back(){/** do nothing */}
};

class C_Vec: public Container{
public:
    void push_back(Question& q){qvec.push_back(q);}
    void pop_back(){qvec.pop_back();}
    int size(){return qvec.size();}
    Question& back(){return qvec.back();}
};

class C_List: public Container{
public:
    void push_back(Question& q){qlist.push_back(q);}
    void pop_back(){qlist.pop_back();}
    int size(){return qlist.size();}
    Question& back(){return qlist.back();}
};

int main(){

    Container *store;
    char user_in;

    cout << "Before we begin please select a storage container:" << endl
         << "a) Linked List" << endl
         << "b) Vector" << endl << ':';

    cin >> user_in;

    if(tolower(user_in) == 'a'){
        C_List l;
        store = &l;
    }else{
        C_Vec v;
        store = &v;
    }
}

3 个答案:

答案 0 :(得分:3)

您有几种选择。如果您需要在运行时决定使用哪个容器,那么多态(继承)可能会运行良好。

#include <vector>
#include <list>
#include <memory>

struct Question {};

// runtime
struct Question_container {
  virtual const Question& get_question() = 0;
  virtual int questions_size() = 0;
  virtual void push_back(const Question&) = 0;
  virtual ~Question_container() = default;
};

struct Vector_question_container : Question_container {
  const Question& get_question() override { return qv.back(); }
  int questions_size() override { return qv.size(); }
  void push_back(const Question& q) override { qv.push_back(q); }
private:
  std::vector<Question> qv;
};

struct List_question_container : Question_container {
  const Question& get_question() override { return qv.back(); }
  int questions_size() override { return qv.size(); }
  void push_back(const Question& q) override { qv.push_back(q); }
private:
  std::list<Question> qv;
};

int main()
{
  // some how figure out which container to use
  std::unique_ptr<Question_container> qc{new Vector_question_container()};
}

如果您可以在编译时进行选择,则可以将基础序列设为模板(甚至模板模板)参数。

// CompileTime
template<typename Sequence>
struct Question_container_c {
  const Question& get_question() { return s.back(); }
  int questions_size() { return s.size(); }
  void push_back(const Question& q) { s.push_back(q); }
private:
  Sequence s;
};

int main()
{
  Question_container_c<std::list<Question>> qlc;
  Question_container_c<std::vector<Question>> qvc;

  return 0;
}

虽然您也可以让算法在迭代器上运行,并将容器的选择留给用户。对于某些方法(例如push_back),这可能会很难,但它实际上并没有执行任何其他方法,而是已经提供的正常push_back

答案 1 :(得分:2)

为了补充@ pmr的答案,如果你想以惯用的方式做,你可以创建一个适配器接口:

class IContainer {
public:
    virtual ~IContainer() {}
    virtual void push_back(const Question & q) = 0;
    virtual void pop_back() = 0;
    virtual const Question & back() const = 0;
    virtual unsigned int size() const = 0;
};

通用实施:

template <class T>
class Container: public IContainer {
private:
    T m_container;

public:
    virtual void push_back(const Question & q) {
        m_container.push_back(q);
    }

    virtual void pop_back() {
        m_container.pop_back();
    }

    virtual const Question & back() const {
        return m_container.back();
    }

    virtual unsigned int size() const {
        return m_container.size();
    }
};

所以你可以这样做:

std::unique_ptr<IContainer> pctr;
if (choice) {
    pctr.reset(new Container<std::vector<Question>>);
}
else {
    pctr.reset(new Container<std::list<Question>>);
}
std::cout << pctr->size();

答案 2 :(得分:1)

我认为您的方法的最佳方法是使用迭代器。迭代器是作为容器抽象而发明的(当然,由于容器的不同行为,你不能100%抽象,但无论如何你有一个比没有更好的解决方案)。