自动将指向派生类的指针列表转换为指向基类的指针列表

时间:2012-10-12 23:15:46

标签: c++ inheritance stl

让我们说我有一个基类和派生类,以及一个带有指向基类的stl向量的函数:

class A { public: int x; };

class B : public A { };

void foo(const vector<A*> &va) {
    for (vector<A*>::const_iterator it = va.begin(); it < va.end(); it++)
        cout << (*it)->x << endl;
}

有没有办法将指针列表传递给派生类?即:

vector<B*> vb;
// ... add pointers to vb ...
foo(vb);

以上将导致以下编译器错误:

error: could not convert ‘vb’ from ‘std::vector<B*>’ to ‘std::vector<A*>’

即使B *可以转换为A *。

最后,如果有一个普通指针的解决方案,它是否也适用于boost共享指针?

4 个答案:

答案 0 :(得分:5)

std::vector<B*> and std::vector<A*>在技术上是无关的。 C ++不允许你想要的东西。

一种解决方法......为什么没有std::vector<Base*>并插入Derived个对象?这就是多态性,动态调度等等。

答案 1 :(得分:2)

您可以从派生的基本指针向量创建基本指针的临时向量:

std::vector<B*> bv;
foo(std::vector<A*>(bv.begin(), bv.end())); 

但是这要求foo接受const引用而不是像你的例子那样引用,效率非常低,需要内存分配和复制,

其他,首选的解决方案是让你的foo成为一个功能模板:

template <class T>
void foo(std::vector<T*>& v);

为确保foo仅用于A派生,请使用type_traits和SFINAE技术,请注意您只使用第一个参数调用foo,第二个仅用于消除此函数模板类型不是来自A(SFINAE):

#include <type_traits>

template <class T>
void foo(std::vector<T*>& av,
         // don't use this second param 
         typename std::enable_if<std::is_base_of<A,T>::value>::type* = 0)

答案 2 :(得分:2)

正如@Science_Fiction之前所说的那样,拥有一个包含指向基本类型的指针的向量并在其中插入指向基本类型和派生类型的指针更有意义,但是如果你不控制这些数组的创建,那么你可以使用模板:

template <class T>
inline void foo(const vector<T*>& v)
{
    for (vector<T*>::const_iterator it = v.begin(); it < v.end(); ++it)
    {
        A* a = (A*) *it;
        cout << a->x << endl;
    }
}

答案 3 :(得分:1)

您无法将vector<B*>传递给foo,因为这些类型不兼容 - B*可隐式转换为A*并不会产生任何影响。

您可以做的是创建一个正确类型的新vector,例如:

vector<B*> vb;
// ... add pointers to vb ...

vector<A*> va(vb.size());
std::transform(vb.begin(), vb.end(), va.begin(),
               [] (B* p) { return static_cast<A*>(p); });