将std :: vector作为参数传递的正确方法是什么?

时间:2017-01-04 06:56:32

标签: c++ c++11 vector stl reference-wrapper

我想传递一个填充了基于同一类的对象的向量。 std::reference_wrapper和无引用都无法解决问题。 解决这个问题的正确方法是什么?

class MyClass
{
public:
    MyClass(int){};
    virtual void print() const {
        std::cout<<"MyClass"<<std::endl;
    }
};
class MySubClass : public MyClass
{
public:
    MySubClass(int a):MyClass(a){};
    virtual void print() const {
        std::cout<<"MySubClass"<<std::endl;
    }
};
void test(const std::vector<std::reference_wrapper<MyClass>>& v)
{
    for (const auto& c : v) {
        c.get().print();
    }
}
void test(const std::vector<MyClass>& v)
{
    for (const auto& c : v) {
        c.print();
    }
}
int main() 
{
    {
        MySubClass s(2);
        std::vector<MyClass> v;
        v.push_back(s);
        test(v);//print MyClass, but I need MySubClass
    }
    {
        MySubClass s(2);
        std::vector<std::reference_wrapper<MyClass>> v;
        v.push_back(s);
        test(v);//print MySubClass
        test({2});
        test({s});//wrong ambigious
    }
    return 0;
}

1 个答案:

答案 0 :(得分:1)

{
    MySubClass s(2);
    std::vector<MyClass> v;
    v.push_back(s);
    test(v);//print MyClass, but I need MySubClass
}

此处的问题是您尝试将MySubClass个对象存储在MyClass的向量中。无法存储整个MySubClass,而只存储MyClass父子对象。这与您希望将存储对象视为MySubClass个实例的愿望相冲突。

{
    MySubClass s(2);
    std::vector<std::reference_wrapper<MyClass>> v;
    v.push_back(s);

这解决了以前的问题。引用可以引用其静态类型的子类。但是,请记住,对象不存储在向量中。该对象存储为局部变量s,仅由向量引用。

    test(v);//print MySubClass
    test({2});
    test({s});//wrong ambigious

这里的问题是你有两个重载,其中既没有接受MySubClass,也接受可以从MySubClass的初始化列表初始化的东西。因此,重载分辨率是不明确的。编译器不知道您打算调用哪个重载。

使用显式临时初始化而不是普通初始化列表。

    test(std::vector<MyClass>{2});
    test(std::vector<std::reference_wrapper<MyClass>>{s});

或者不要使用重载,而是使用唯一命名的函数。

void test(const std::vector<std::reference_wrapper<MyClass>>& v)
void test2(const std::vector<MyClass>& v)