如何在派生函数对象列表中进行迭代,并访问派生对象的成员变量。

问题描述 投票:0回答:1

我有一个函数对象定义。

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,我得到父类的成员变量。我可以写getters,用这种方式获取派生函数对象的成员变量,但如果函数对象有很多成员变量,那似乎很费劲。有没有其他方法可以实现?

c++ functor derived-class
1个回答
3
投票

你的派生类定义了另一个成员,名为 desc 在现有 BaseFunctor::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 必须有一个 virtual 如果派生类的对象被通过 BaseFunctor*而你的代码表明了这一点。
  • 衍生类重写函数应该使用 override 而不是 virtual 以便编译器在你试图覆盖一个不存在的函数或有不同的参数和返回类型时捕捉错误。有了 virtual 它引入了一个新的同名函数重载,在这种情况下。
  • std::unique_ptr 是用来避免手动清理和泄漏内存的。
  • BaseFunctor::desc 使 const中的初始化器列表中进行初始化,因此必须在 BaseFunctor. 这也使得 BaseFunctor 不可复制和不可移动,避免了派生类对象的意外复制。

2
投票

调用 定数 的函数,参数相同,在注释中讨论。参见(重载)函数 call_all:

#include <iostream>

void call_all() {
    // Does nothing, just stops the recursion.
}

template<typename Current, typename... Args>
void call_all(Current current_function, Args... args) {
    current_function();
    call_all(args...);
}

void func1() {
    std::cout << "func1" << std::endl;
}

void func2() {
    std::cout << "func2" << std::endl;
}

int main() {
    // Pass anything that implements operator() here.
    call_all(func1, func2);
}
© www.soinside.com 2019 - 2024. All rights reserved.