我有一个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>>>>'
有没有任何可能的方法来实现这个没有任何铸造?
答案 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);
}
}
}
}