![](/img/trans.png)
[英]c++ std::vector of functions passed as a parameter of a class method
[英]C++ std::function to take functions with sub class parameter
如果我有一个 function 包装器作为std::function<void(const Parent&)>
,有没有办法允许它采用Parent
作为参数,例如[](const Child& child){...}
,其中Child
是Parent
的子类。
以下内容无法编译。 在线 IDE链接。
#include <iostream>
#include <functional>
class Parent {
public:
virtual void say() const {
std::cout<<"I am parent"<<"\n";
}
};
class Child: public Parent {
public:
void say() const {
std::cout<<"I am child"<<"\n";
}
};
typedef std::function<void(const Parent&)> Wrapper;
int main() {
Wrapper func=[](const Child& child){ // of course works if Child->Parent
child.say();
};
Child c;
func(c);
return 0;
}
语言不允许这样做,因为这可能会导致不一致。
根据您对Wrapper
的定义,以下代码应该是合法的:
Wrapper f;
Parent x;
... // Initialize f with a legitimate function dealing Parent
f(x);
现在想象两个类:
class Child1: public Parent {
public:
void say() const {
std::cout<<"I am child1"<<"\n";
}
virtual void tell() const {
std::cout<<"This is specific to child1"<<"\n";
}
};
class Child2: public Parent {
public:
void say() const {
std::cout<<"I am child2"<<"\n";
}
};
以下代码也是有效的,因为Child1
和Child2
派生自Parent
:
Child1 y;
Child2 z;
f(y);
f(z);
如果您被允许为包装器分配带有子参数而不是父参数的 function,那么您也可以执行以下操作:
Wrapper f=[](const Child1& child){ // if this is legitimate
child.tell(); // then this would be legitimate
};
你会很容易猜到f(x)
和f(z)
不起作用,尽管f
的类型应该允许它。
你可以做的,但这是更冒险的事情,是制作一个包装器 function ,它接受一个Parent
参数并且向下转换是一个Child
。 但我不推荐它,除非没有其他解决方案并且只能格外小心。
using Wrapper = std::function<void(const Parent&)>;
int main() {
Wrapper func=[](const Parent& parent){
auto child=dynamic_cast<const Child*>(&parent);
if (child)
child->say();
else std::cout<<"OUCH!!! I need a child"<<std::endl;
};
Parent x;
Child c;
func(c);
func(x);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.