Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/129.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;,多态性与迭代器_C++_Class_Iterator_Polymorphism_Subclass - Fatal编程技术网

C++ C++;,多态性与迭代器

C++ C++;,多态性与迭代器,c++,class,iterator,polymorphism,subclass,C++,Class,Iterator,Polymorphism,Subclass,我想要一个存储接口(抽象类)和一组存储实现(SQLite、MySQL、Memcached…),用于存储已知类的对象和从存储中检索子集。 对我来说,清晰的界面是: class Storable{int id; blah; blah; blah; string type;}; class Storage{ virtual Storage::iterator get_subset_of_type(string type) = 0; virtual Storage::iterator e

我想要一个存储接口(抽象类)和一组存储实现(SQLite、MySQL、Memcached…),用于存储已知类的对象和从存储中检索子集。
对我来说,清晰的界面是:

class Storable{int id; blah; blah; blah; string type;};
class Storage{
    virtual Storage::iterator get_subset_of_type(string type) = 0;
    virtual Storage::iterator end)_ = 0;
    virtual void add_storable(Storable storable) = 0;
};
然后创建实现该接口的存储实现。现在,我的问题是:

  • 迭代器不能是多态的,因为它们是通过值返回的
  • 对于给定的存储实现,我不能只将Storage::iterator子类化
  • 我考虑使用一个包装器迭代器来包装和执行存储实现子类的多态类型上的pimpl,但是我需要使用动态内存并到处分配

有什么提示吗?

我看不出存储多态性的好处

无论如何,请注意迭代器根本不必是多态的


它只需使用存储类中的虚拟方法即可实现其功能。这些方法可以很容易地在子代中被重写(创建所需的功能)。

这似乎是一种动态分配与更改迭代器状态大小(无需重新编译客户端)能力的对比。

我不确定这是一个问题的确切原因。您只需要实现所有迭代器操作符(增量、取消引用等),以便它们调用
存储
对象的虚拟方法。

您可以尝试boost::iterator,它提供了几个适配器和外观


使用数据库引擎进行存储的事实并没有改变这样一个事实,即这里的内容基本上是一个容器类

简言之,几乎可以肯定的是,您应该使用在存储的对象类型上实例化的类模板。存储引擎中的变化可以通过继承或第二个模板参数来处理。使用模板参数给出编译时多态性,而继承给出运行时多态性(即,您可以在运行时更改存储引擎)


您可能想从adobe::any_iterator或any_iterator的其他实现中获得一些灵感(或者您可能会为自己省去很多麻烦,在遇到问题之前使用它)。

看看adobe::any_iterator或any_iterator的其他实现(http://thbecker.net/free_software_utilities/type_erasure_for_cpp_iterators/any_iterator.html). 它实现了多态迭代器的概念,但您仍然需要处理任何按值(按值返回、按值传递等)的迭代器。

实际使用不同类型容器的算法代码必须写入模板函数(可能是成员函数),模板函数通过模板参数获取类型。 在编译时解析。对于模板函数的每个实例,确切的迭代器类型是已知的

如果您确实需要运行时解析,则需要添加分派以调用上述模板函数的不同实例。虚拟函数应该调用实际的algorythm模板函数,但这在某些模板类中是一个虚拟函数重写(即,虚拟函数将为每个实例单独编译,并调用algorythm模板函数的不同实例)。
如果您需要双重/多重分派,就这样吧。太糟糕了,C++不支持函数在多个参数上是虚拟的,你必须使用任何常用的习惯用法来进行双重调度。但是对实际算法函数的调用应该在分派解决之后进行。

如果您想要一个用于迭代的虚拟接口,像这样的

#include <iostream>
#include <iterator>

struct Iterable {
    virtual int current() = 0;
    virtual void advance() = 0;
  protected:
    ~Iterable() {}
};

struct Iterator : std::iterator<std::input_iterator_tag,int> {
    struct Proxy {
        int value;
        Proxy(const Iterator &it) : value(*it) {}
        int operator*() { return value; }
    };
    Iterable *container;
    Iterator(Iterable *a) : container(a) {}
    int operator*() const { return container->current(); }
    Iterator &operator++() { container->advance(); return *this; }
    Proxy operator++(int) { Proxy cp(*this); ++*this; return cp; }
};

struct AbstractStorage : private Iterable {
    Iterator iterate() {
        return Iterator(this);
    }
    // presumably other virtual member functions...
    virtual ~AbstractStorage() {}
};

struct ConcreteStorage : AbstractStorage {
    int i;
    ConcreteStorage() : i(0) {}
    virtual int current() { return i; }
    virtual void advance() { i += 10; }
};

int main() {
    ConcreteStorage c;
    Iterator x = c.iterate();
    for (int i = 0; i < 10; ++i) {
        std::cout << *x++ << "\n";
    }
}
#包括
#包括
可结构化{
虚int current()=0;
虚空前进()=0;
受保护的:
~Iterable(){}
};
结构迭代器:std::迭代器{
结构代理{
int值;
代理(常量迭代器&it):值(*it){}
int运算符*(){返回值;}
};
Iterable*容器;
迭代器(Iterable*a):容器(a){}
int运算符*()常量{return container->current();}
迭代器和运算符++(){container->advance();返回*this;}
代理运算符++(int){Proxy cp(*this);++*this;返回cp;}
};
结构AbstractStorage:私有Iterable{
迭代器迭代器(){
返回迭代器(this);
}
//可能还有其他虚拟成员函数。。。
虚拟~AbstractStorage(){}
};
结构具体存储:抽象存储{
int i;
具体存储():i(0){}
虚int current(){return i;}
虚拟void advance(){i+=10;}
};
int main(){
混凝土仓c;
迭代器x=c.iterate();
对于(int i=0;i<10;++i){

std::cout之所以需要多态行为,是因为我将有几个在运行时需要可交换的存储,比如primarysecondary,它们可以是不同的类型。@Arkaitz你仍然不需要多态性,如果你不知道具体的存储实际上是什么/做什么,你就需要多态性。这就是重点,我可能是使用主(sqlite)和次(memcached),然后在运行时交换它们,因此我需要使用公共接口,因此在那里使用多态性,因为在任何给定时刻,我都不知道我的主或次接口是哪种类型。由于这个提示,我能够弄清楚如何实现类似于
Iterable
“接口”的东西:嗯,这正是我想做的,使用继承来处理不同的引擎,我只是在如何正确迭代子集上遇到了问题,因为我不能只继承和重写迭代器。@Arkaitz:就像我说的,你可能应该看看DTL的总体设计。在任何情况下,存储引擎的变化与变化是正交的在存储的类型中,后者决定了迭代器的类型。你可以,如果迭代器中的状态相同(即只覆盖迭代器的方法)@jerry,我认为他的观点是迭代器