如何多态地使用数组或指针向量?
How to use arrays or vectors of pointers polymorphically?
我在许多不同的帖子中都读过关于这个问题的内容,数组不能被多态处理,应该使用指针数组来代替,我很清楚其背后的原因。
但是,我找不到它是如何完成的示例,而且我似乎无法让它工作。考虑以下代码:
#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*>
我是不是遗漏了什么或者设计是否存在根本性缺陷?提前致谢。
std::vector<Derived*>
和std::vector<Base*>
是不同的类型,它们之间没有转换。不过看来你需要的是
std::vector<Base*> bar;
foo(bar);
即让多态性在向量的元素级别工作。
但是,请注意,为了在通常意义上使用多态性,Derived
必须 publicly 从 Base
:
继承
class Derived : public Base
^^^^^^
或
struct Derived : Base
Am I missing something or is the design even fundamentally flawed?
无法将 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*>
。
要完成 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;
}
我在许多不同的帖子中都读过关于这个问题的内容,数组不能被多态处理,应该使用指针数组来代替,我很清楚其背后的原因。
但是,我找不到它是如何完成的示例,而且我似乎无法让它工作。考虑以下代码:
#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*>
我是不是遗漏了什么或者设计是否存在根本性缺陷?提前致谢。
std::vector<Derived*>
和std::vector<Base*>
是不同的类型,它们之间没有转换。不过看来你需要的是
std::vector<Base*> bar;
foo(bar);
即让多态性在向量的元素级别工作。
但是,请注意,为了在通常意义上使用多态性,Derived
必须 publicly 从 Base
:
class Derived : public Base
^^^^^^
或
struct Derived : Base
Am I missing something or is the design even fundamentally flawed?
无法将 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*>
。
要完成 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;
}