c++ - 如何迭代派生函数对象列表并访问派生对象成员变量

标签 c++ functor derived-class

我有一个函数对象定义:

struct BaseFunctor
{
    std::string desc = "Not this one!";
    virtual double operator()(double a, double (*func) (double)) = 0;
};

以及一组派生函数对象定义:

struct DerivedFunctor1 : public BaseFunctor
{
    std::string desc = "Yes this!";
    virtual double operator()(double a, double (*func) (double))
    {
        return a * func(a);
    }
};

struct DerivedFunctor2 : public BaseFunctor
{
    std::string desc = "This is also correct!";
    virtual double operator()(double a, double (*func) (double))
    {
        return 5 * a * func(a);
    }
};

它们按以下方式实例化和使用:

double f1(double x){
    return x*x+x;
}

template <typename T, typename F>
void do_something(T &func, F &derived)
{
    double a = 1.0;
    double res = derived(a, func);
    std::cout << derived.desc << std::endl;
    std::cout << "Result is: " << res << std::endl;

}

int main()
{
    std::vector<BaseFunctor*> functors;
    DerivedFunctor1 *derived1 = new DerivedFunctor1;
    DerivedFunctor2 *derived2 = new DerivedFunctor2;
    functors.push_back(derived1);
    functors.push_back(derived2);

    for (auto &f : functors)
    {
        do_something(f1, *f);
    }
}

现在,这两个函数对象派生自 BaseFunctor 的原因是我可以将它们收集在标准容器中并迭代它们。是否有其他更有效的方法来迭代函数对象?

其次,运行代码输出

Not this one!
Result is: 2
Not this one!
Result is: 10

当我尝试访问成员变量desc时,我得到了父类的成员变量。我可以编写 getter 并以这种方式访问​​派生函数对象的成员变量,但如果函数对象有很多成员变量,这似乎需要大量工作。还有其他方法可以实现这一目标吗?

最佳答案

除了现有的 BaseFunctor::desc 之外,您的派生类还定义了另一个名为 desc 的成员。

您更需要的是使用正确的字符串初始化BaseFunctor::desc。示例:

#include <iostream>
#include <memory>
#include <vector>

struct BaseFunctor {
    std::string const desc;
    virtual double operator()(double a, double (*func) (double)) = 0;
    virtual ~BaseFunctor() noexcept = default;
protected:
    BaseFunctor(std::string desc) noexcept
        : desc(move(desc))
    {}
};

struct DerivedFunctor1 : public BaseFunctor {
    DerivedFunctor1() : BaseFunctor("Yes this!") {}
    double operator()(double a, double (*func) (double)) override { return a * func(a); }
};

struct DerivedFunctor2 : public BaseFunctor {
    DerivedFunctor2() : BaseFunctor("This is also correct!") {}
    double operator()(double a, double (*func) (double)) override { return 5 * a * func(a); }
};

template <typename T>
void do_something(T &func, BaseFunctor &derived) {
    double a = 1.0;
    double res = derived(a, func);
    std::cout << derived.desc << '\n';
    std::cout << "Result is: " << res << '\n';
}

double f1(double a) noexcept { return a * a + a; }

int main() {
    using P = std::unique_ptr<BaseFunctor>;
    std::vector<P> functors;
    functors.push_back(P(new DerivedFunctor1));
    functors.push_back(P(new DerivedFunctor2));
    for (auto &f : functors)
        do_something(f1, *f);
}

其他一些更改:

  • 如果派生类的对象通过 BaseFunctor* 删除,并且您的代码建议这样做,BaseFunctor 必须具有一个virtual 析构函数。
  • 派生类重写函数应使用 override 而不是 virtual,以便编译器在您尝试重写不存在或具有不同参数的函数时捕获错误,并且/或返回类型。在本例中,使用 virtual 引入了一个同名的新函数重载。
  • std::unique_ptr 用于避免手动清理和内存泄漏。
  • BaseFunctor::desc 设为 const,因此必须在 BaseFunctor 的初始化器列表中对其进行初始化。这也使得 BaseFunctor 不可复制且不可移动,从而避免了通过切片意外复制派生类对象。

关于c++ - 如何迭代派生函数对象列表并访问派生对象成员变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61565796/

相关文章:

haskell - fmap 的单子(monad) "versions"的名称是什么?

haskell - Haskell中有态射吗?

c# - 如何强制派生类包含具有默认值的某些属性

c++ - 以类对象和结构对象 c++ 开始线程

c++ - 如何通过定义派生类的构造函数来实例化两个基类的私有(private)数据成员?

c++ - 使用模板构造函数,模板参数推导/替换失败,为什么?

c++ - boost::graph同构的使用

c++ - C++ 20:左半部分或右半部分是否有子范围?

c++ - BOOST::CRC使用process.block()方法创建校验和

c++ - 从 std::function 继承,语法和用法?