如何用派生类向量作为参数实现函数

时间:2010-11-26 04:10:42

标签: templates vector implementation idioms

(与之前提到的unanswered question相关)。我想实现一个只能用相关类的向量作为参数调用的函数。

对于eq

如果我们有

class A;
class B: public A;
class C: public A;
class D

then it should be possible to call function with vector<A*>,vector<B*> or 
vector <C*> but not vector <D*>

任何建议

2 个答案:

答案 0 :(得分:1)

duck-typing对你来说足够好吗?考虑一下这段代码

template <class T>
void my_function (std::vector <T*> const &values) {
    // Use features of A* here
}

如果使用指向T的指针不支持的功能,则无法编译。通过使用A的功能,我认为应该保证指向BC的指针也能按预期工作。但是,可以使用D *向量调用此函数,前提是D的接口符合my_function尝试执行的操作。

答案 1 :(得分:1)

我猜你已经尝试过创建像

这样的方法
void doSomething(std::vector<A*>& things)
{
}

并尝试传递

std::vector<B*> bList = ...;
doSomething(bList);

正确?

为什么编译器会抱怨?因为没有意义。考虑doSomething()尝试执行

things.push_back(new C());

这不起作用,因为“事物”实际上是std::vector<B*>。但是,如果它是std::vector<A*>,则push_back将起作用。

那么我们可以从中学到什么呢?如果你只是从向量中读取,那么你所尝试的只是有意义,但是,向量不是只读容器。

一个简单的包装器显示了一个可能的解决方案(当然,包装器可以根据您的需要进行调整)。但是,我必须指出,使用虚拟方法可能会导致性能损失。

class A {};
class B : public A {};

template <class Base>
class AbstractVectorWrapper
{
public:
    virtual size_t size() const = 0;
    virtual Base* getElementAt(int index) const = 0;
};
template <class Base, class Derived>
class VectorWrapper : public AbstractVectorWrapper<Base>
{
private:
    std::vector<Derived*> m_vector;
public:
    explicit VectorWrapper(std::vector<Derived*> const& vector)
        : m_vector(vector)
    {
    }
    virtual size_t size() const
    {
        return m_vector.size();
    }
    virtual Base* getElementAt(int index) const
    {
        return m_vector[index];
    }
};

void doSomething(AbstractVectorWrapper<A> const& wrapper)
{
    for (size_t i=0;i<wrapper.size();i++)
    {
        A* a = wrapper.getElementAt(i);
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    std::vector<A*> as;
    std::vector<B*> bs;
    doSomething(VectorWrapper<A,B>(bs));
    doSomething(VectorWrapper<A,A>(as));


    return 0;
}