我已经在很多不同的帖子中读到了这个问题,不应该对数组进行多态处理,而应该使用指针数组,而且背后的推理对我来说很清楚。
但是,我找不到它是如何完成的例子,我似乎无法让它工作。请考虑以下代码:
#include <vector>
class Base
{
public:
Base();
virtual ~Base();
};
class Derived : Base
{
public:
Derived();
~Derived();
};
void foo( std::vector<Base*> )
{
// do something
}
int main()
{
std::vector<Derived*> bar;
foo(bar);
return 0;
}
编译它会显示错误消息
could not convert 'bar' from 'std::vector<Derived*>' to 'std::vector<Base*>
我是否遗漏了某些东西,或者设计是否存在根本缺陷?提前谢谢。
答案 0 :(得分:6)
std::vector<Derived*>
和std::vector<Base*>
是不同的类型,它们之间没有转换。但看起来你需要的是
std::vector<Base*> bar;
foo(bar);
即。让多态性在向量元素的层次上起作用。
但请注意,为了在通常意义上使用多态,Derived
必须从Base
继承公开:
class Derived : public Base
^^^^^^
或
struct Derived : Base
答案 1 :(得分:2)
要完成juanchopanza的回答,您可以使用std::vector<Derived*>
:
void itemfoo(Base* item)
{
// do something
}
template<typename Iter>
void foo(Iter begin, Iter end) {
// do stuff per element
while(begin != end)
itemfoo(*begin++);
}
int main()
{
std::vector<Derived*> bar;
foo(bar.begin(), bar.end());
return 0;
}
如果你需要对整个范围进行操作并按Base*
进行操作,那么你可以这样做:
void foo(Base** begin, Base** end) {
// do stuff on range [begin, end)
}
int main()
{
std::vector<Derived*> bar;
if(bar.empty())
foo(nullptr, nullptr); // or however you handle the empty range
else
foo(&bar[0], &bar[0] + bar.size());
return 0;
}
答案 2 :(得分:1)
我是否遗漏了某些东西,或者设计是否存在根本缺陷?
std::vector<Derived*>
的对象无法自动转换为std::vector<Base*>
。它们是两种完全不同的类型。
我可以考虑以下选项来解决这个问题:
将foo
更改为接受std::vector<Derived*>
。
void foo( std::vector<Derived*> )
{
// do something
}
将foo
更改为功能模板。
template <typename T>
void foo( std::vector<T*> )
{
// do something with the implicit understanding that
// T is derived from Base.
}
更改主叫代码以使用std::vector<Base*>
。