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

C++ - Alternative to base-class function-pointer calls

本文关键字:方法 调用 指针 基类 类函数 C++      更新时间:2023-10-16

我发现很多帖子都非常清楚地指出派生类函数不能分配给基类函数指针。所以我想知道,如何处理和解决以下情况:

假设我有以下基本class

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

这个类的主要目的是有一个"functions"性质的associative-array

所以我想要的是每个派生的孩子都能够将他们的方法添加到"关联数组"中。

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

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

编辑:用例示例

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

(this->*associativeArray.at("algorithm"))();

我能得到的最接近你想要的就是使用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;
}

我想你需要的是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);  
}
};

查看此演示