使用类模板的隐式转换

Implicit conversion with class templates

本文关键字:转换      更新时间:2023-10-16

使用下一个定义

class A {};
class B : public A {};
void f(A* a) {}

调用f(new B)是可能的,因为B*隐式转换为A*,对吧?

然而,当对std::vector这样的类模板执行同样的操作时,会产生编译错误。

void f(std::vector<A*> v)
{}
int main()
{
    std::vector<B*> v;
    f(v); //error! "no suitable user-defined conversion..."
    return 0;
}

为什么?

std::vector<B*>std::vector<A*>是完全不同的类型,但B是从A派生而来的。要将数据从std::vector<B*>复制到std::vector<A*>,请使用std::copystd::back_inserter:

#include <algorithm> // std::copy
#include <iterator>  // std::back_inserter
std::vector<B*> b;
std::vector<A*> a;
std::copy( b.begin(), b.end(), std::back_inserter( a ) );

或使用统一初始化初始化a

std::vector<B*> b;
std::vector<A*> a{ b.begin(), b.end() };

std::vector<B*>std::vector<A*>完全不同,因为它们的模板参数的类型不同。

作为一种变通方法,您可以使用矢量的另一个ctor,即template<class InputIt> std::vector::vector(InputIt first, InputIt last),例如:

f(std::vector<A*>(v.begin(), v.end()));

或者只是(需要c++11)

f({v.begin(), v.end()});

实时

正如注释中所指出的,std::vector<A*>std::vector<B*>是不同的类型。这并不妨碍您将B*对象存储在std::vector<A*>向量中。正如您推测的那样,基类指针可以指向派生对象,这就是为什么您可以将它们存储在基类向量中。

您还应该在f的原型中引用v

最后一句话:你其实并不需要std::vector<B*>