C ++-基类函数指针调用的替代方法

问题描述 投票:5回答:2

我发现许多帖子都清楚地指出将派生类函数CANNOT分配给基类函数指针。因此,我想知道如何解决以下情况:

假设我具有以下基数class

class base {
protected:
    typedef void (base::*base_fp)();
    typedef std::map<std::string, base_fp> array;

    array associativeArray;    
};

此类的主要目的是拥有“associative-arrayof functions”属性。

所以,我希望每个派生子代都能将其方法添加到“ associativeArray”中

this->associativeArray["Method"] = &child::method; // from the child class

我最初使用此方法的目的是根据需要调用不同的方法而不使用条件语句。它将在try-catch块中处理不存在的索引的情况。由于我原来的方法是不可能的,那么正确的方法是什么?

EDIT:用例示例

假设关联数组是“算法” functions的数组。然后对于用户“算法”输入,我应该能够调用在子类中定义的相应方法

(this->*associativeArray.at("algorithm"))();
c++ inheritance function-pointers associative-array member-function-pointers
2个回答
4
投票

我能最接近您想要的是使用std::function(自C ++ 11起可用)。首先,出于现代化目的和使用typedef,我们将更改您的std::function

class base {
protected:
    using base_fp = std::function<void ()>;
    using fn_array = std::map<std::string, base_fp>;
    fn_array fns;

public:
    void call_fn(std::string const &fn_name) {
        auto it = fns.find(fn_name);
        if(it != fns.end()) {
            it->second();
        }
        else {
            // error case
        }
    }
};

因为fn_array存储了std::function,所以它将与我们视为可调用对象的任何事物一起使用。这不能直接用于成员函数(std::invoke可以解决问题,但是我没有使用该库功能),但是可以使用平凡的闭包来获得类似的行为。

class derived : public base {
public:
    derived() {
        fns["foo"] = [this]() { foo(); };
    }

private:
    void foo() {
        std::cout << __PRETTY_FUNCTION__ << '\n';
    }
};

您可以使用如下代码来利用它:

int main() {
    derived d;
    d.call_fn("foo");
    return 0;
}

0
投票

我想您需要的是static_cast,因为在带有相同签名的两个函数之间使用是安全的,甚至是从相同的类层次结构中产生的。

class base {

   protected:
     typedef void (base::*fn)() ;
     base(){
     fn_arr["foo"]=&base::foo;  
     }  
     void foo()  {
        cout << "i'm foo" << endl;
     }

   public:
     map<std::string, fn> fn_arr;
};

class derived : public base {

   protected:
      void bar() {
          cout <<"i'm bar" << endl;
      }

   public:
      derived() {
          fn_arr["bar"]=static_cast<fn>(&derived::bar);  
      }
};

see this demo

© www.soinside.com 2019 - 2024. All rights reserved.