迭代C++ list <derived>作为基类

BCS*_*BCS 1 c++ templates iterator base-class

我想要做的是:

class Ba { }
class Da : public Ba {}
class Db : public Ba {}

class Bb // abstract base class that must not be a template.
{
    void Process()
    {
        list<Ba*>::iterator pos;
        // I known the derived class will also derive
        // from list<Dx*> where Dx derives from Ba
        for(pos = this->begin(); pos < this->end(); pos++)
            something(*pos);
    }
}

template<T> class L : public Bb , list<T*> // T is always derived from Ba
{
}
Run Code Online (Sandbox Code Playgroud)

但那是无效的.那么下一个最好的东西是什么?

一个交替的公式有一个全局Process得到一个Bb指针,其中类型不知道直到运行时:

void GlobalProcess(Bb* bb) // don't know what kind of Bb (which L) got passed in.
{
        list<Ba*>::iterator pos;
        // I known the derived class will also derive
        // from list<Dx*> where Dx derives from Ba
        for(pos = bb->begin(); pos < bb->end(); pos++)
            something(*pos);
}
Run Code Online (Sandbox Code Playgroud)

我有几个理由这样做,但大约一半是感觉到C++系统的边缘.


我能提出的最简单的问题形式是我需要迭代一个list<D*>代码,其中我允许在编译时使用的所有信息都D来源于B.这种情况可能来自于list<D>通过指向抽象基类的指针或其自身在基类中的代码.

如果只是list<D*>::iterator衍生出来的话,这一切都会好起来的list<B*>::iterator

Eva*_*ran 8

首先,不要继承std::list<>,STL中的类(有一些小的例外)并不意味着派生自.他们没有虚拟成员,这样做没有任何好处,只会导致问题.

你的问题有点模糊和混乱.但假设你想这样做:

struct A {};
struct B : public A {};
std::list<B> l;

for(std::list<A>::iterator it = l.begin(); it != l.end(); ++it) {
    whatever(*it);
}
Run Code Online (Sandbox Code Playgroud)

显然这是无效的.但你可以这样做:

struct A {};
struct B : public A {};
std::list<B> l;


void whatever(A& a) {
    // do something with an A
}

std::list<B> l;
for(std::list<B>::iterator it = l.begin(); it != l.end(); ++it) {
    whatever(*it);
}
Run Code Online (Sandbox Code Playgroud)

或者更好的是:

struct A {};
struct B : public A {};
std::list<B> l;

void whatever(A& a) {
    // do something with an A
}

std::for_each(l.begin(), l.end(), whatever);
Run Code Online (Sandbox Code Playgroud)

编辑:

要做你想做的事,你只需要做一些额外的模板工作,如下所示:

class Ba {};
class Da : public Ba {};
class Db : public Ba {};

template <class T>
class Bb {
    void Process() {
        list<T>::iterator pos;
        for(pos = begin(); pos < end(); pos++)
            something(*pos);
    }
}

template <class T>
class L : public Bb<T>, std::list<T> {
}
Run Code Online (Sandbox Code Playgroud)

或者您可以像这样制作流程和界面:

template <class T>
class Bb {
public:
    virtual void Process() = 0;
}

template <class T>
class L : public Bb<T>, std::list<T> {
public:
    virtual void Process() {
        list<T>::iterator pos;
        for(pos = begin(); pos < end(); pos++)
            something(*pos);
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,这将是迄今为止最好不要继承std::list<>,因为它几乎肯定会导致错误.最好std::list<T>成为L班上的一员.