为派生类的向量调用适当的方法

时间:2018-05-26 15:31:35

标签: c++ stdvector unique-ptr stdmap

我有一个key和std :: vector的映射以及下面的代码。

std::map<Key, std::vector<std::unique_ptr<Foo>>> myMap;

class Foo
{
    // removed for brevity
};

class Boo : public Foo
{
    // removed for brevity
};

class Doo : public Foo
{
    // removed for brevity
};

void doSomething(std::vector<std:unique_ptr<Boo>>& booList)
{
    // removed for brevity
}

void doSomething(std::vector<std:unique_ptr<Doo>>& dooList)
{
    // removed for brevity
}

迭代如下;

for(auto& item : myMap)
{
    // removed for brevity
    doSomething(it.second);
}

因此,在迭代地图时,我想根据派生的类类型为地图的每个元素调用适当的函数,但收到以下错误。

non-const lvalue reference to type 'vector<unique_ptr<Boo, default_delete<Boo>>, allocator<unique_ptr<Boo, default_delete<Boo>>>>' cannot bind to a value of unrelated type 'vector<unique_ptr<Foo, default_delete<Foo>>, allocator<unique_ptr<Foo, default_delete<Foo>>>>'

有没有任何可能的方法来实现这个没有任何铸造?

4 个答案:

答案 0 :(得分:0)

如果函数不是类的成员函数,我不认为如果不进行转换就可以这样做。否则就无法知道Foo可能被贬低为什么。您可以执行类似的操作来调用指向Foo的链接。

template <class T>
class Foo
{
    virtual void doSomething(std::vector<std:unique_ptr<T>>& FooList);
};

class Boo : public Foo<Boo>
{
    virtual void doSomething(std::vector<std:unique_ptr<Boo>>& BooList) override;
};

class Doo : public Foo<Doo>
{
    virtual void doSomething(std::vector<std:unique_ptr<Doo>>& DooList) override;
};

答案 1 :(得分:0)

通常你会写:

void callByFoo(Foo* foo) {
}

int main() {
    Boo* bp = new Boo();
    callByFoo(bp);
}

但是使用智能ptr你正在初始化引用,所以你有不同类型的引用,所以这不起作用:

void callByFoo(std::unique_ptr<Foo>& fooRef) {
}

int main() {
    std::unique_ptr<Boo> bp = std::make_unique<Boo>();
    callByFoo(bp);
}

我假设与第一个例子比较,就像你写的那样:

void callByFoo(Foo*& fooRef) {
}

int main() {
    Boo* bp = new Boo();
    callByFoo(bp);
}

因此,为了使其工作,使用基指针和类型将匹配,如下例所示:

void callByFoo(std::unique_ptr<Foo>& fooRef) {
}

int main() {
    std::unique_ptr<Foo> bp = std::make_unique<Boo>();
    callByFoo(bp);
}

在您的示例中,您显然必须将方法更改为虚拟,函数签名将如下所示:

void doSomething(std::vector<std:unique_ptr<Foo>>& booList)
{
    // removed for brevity
} 

答案 2 :(得分:0)

你应该有一个虚方法,并迭代向量的每个元素。

以下C ++ 14中的示例:

#include <iostream>
#include <map>
#include <memory>
#include <vector>

using namespace std;

class Foo
{
  public:
    virtual void doSomething() = 0;
};

class Boo : public Foo
{
  public:
    virtual void doSomething() override
    {
        cout << "Boo do something" << endl;
    }
};

class Doo : public Foo
{
  public:
    virtual void doSomething() override
    {
        cout << "Doo do something" << endl;
    }
};

using Key = int;
map<Key, vector<unique_ptr<Foo>>> myMap;

int main()
{
    myMap[10].push_back(make_unique<Boo>());
    myMap[10].push_back(make_unique<Doo>());

    myMap[1000].push_back(make_unique<Doo>());
    myMap[1000].push_back(make_unique<Boo>());

    for (auto& kv: myMap) {
        cout << "key: " << kv.first << endl;
        for (auto& foo: kv.second) {
            foo->doSomething();
        }
    }
}

答案 3 :(得分:0)

如果你不能修改Foo,Boo,Doo的实现,那么你可以定义非成员重载函数,但是不能将向量作为参数而是向量的元素,因为你不能传递向量&lt; B *&gt;期望向量&lt; A *&gt;的函数即使B是A的派生类。然后希望Foo是多态的,你可以通过dynamic_cast选择正确的函数。

#include <iostream>
#include <map>
#include <memory>
#include <vector>

using namespace std;

class Foo
{
    virtual void dummy_function_used_to_have_polymorphism() {}
};

class Boo : public Foo
{
};

class Doo : public Foo
{
};

void doSomething(Boo& boo)
{
    cout << "Boo do something" << endl;
}

void doSomething(Doo& doo)
{
    cout << "Doo do something" << endl;
}

using Key = int;
map<Key, vector<unique_ptr<Foo>>> myMap;

int main()
{
    myMap[10].push_back(make_unique<Boo>());
    myMap[10].push_back(make_unique<Doo>());

    myMap[1000].push_back(make_unique<Doo>());
    myMap[1000].push_back(make_unique<Boo>());

    for (auto& kv: myMap) {
        cout << "key: " << kv.first << endl;
        for (auto& foo: kv.second) {
            if (auto p = dynamic_cast<Boo*>(foo.get())) {
                doSomething(*p);
            } else
            if (auto p = dynamic_cast<Doo*>(foo.get())) {
                doSomething(*p);
            }
        }
    }
}