繁体   English   中英

C++ std::function 采用子 class 参数的功能

[英]C++ std::function to take functions with sub class parameter

如果我有一个 function 包装器作为std::function<void(const Parent&)> ,有没有办法允许它采用Parent作为参数,例如[](const Child& child){...} ,其中ChildParent的子类。

以下内容无法编译。 在线 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";
        }
};

以下代码也是有效的,因为Child1Child2派生自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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM