我想就如何解决我遇到的一个有趣问题提出一些建议。
问题是有两个存储容器,用户可以选择哪个存储容器用于程序的其余部分(编辑:在运行时)。这两个容器是Vector和List,并存储我们要定义的对象类型。可以使用您想要的任何方式访问这两个容器(pop / [i] / ...)您将如何解决此问题?
以下是我最好的(几乎正常工作)解决方案,但我真的很想看看更熟练的C ++专业人士有哪些解决方案。如前所述,如果我采取正确的方法,我真的很感兴趣。这个学期我有超过典型的空闲时间,我打算用它来真正提高我的c ++能力。感谢您的反馈。
首先,我有一个布尔标志,
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);
}
}
注意:请使用标签&#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;
}
}
答案 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%抽象,但无论如何你有一个比没有更好的解决方案)。