如何使用函数指针或虚函数来允许其他程序员定义函数的实现?
How to use function pointers or virtual functions to allow another programmer to define a function's implementation?
我正在编写一个程序,该程序执行一组基本操作,但允许用户填写调用的特定函数(他们在编译之前选择这些函数)。例如,我的程序可能会调用函数filter(input,&output)
但用户可以编写自己的过滤器。
我读到的可能解决这个问题的方法就是函数指针和虚函数。看起来我可以做一些类似的事情
int (*pt2Filter)(float,&float) = NULL;
int IIRFilter(float input, float &output);
pt2Filter=&IIRFilter;
对于函数指针。但这并不能让我跟踪过滤器中的内部状态。
或者,我可以创建一个具有虚拟filter
函数的类myClass
,然后用户将创建一个继承自myClass
并覆盖filter
函数的IIR
类。
class myClass
{
virtual void Filter(float input, float &output);
...
};
class IIR : public myClass
{
float stateVariable;
virtual void Filter(float input, float &output);
}
void IIR::Filter(float input, float &output)
{ //IIR filter done here }
我想我的问题是如何在不知道IIR
类存在的情况下从我的程序中调用过滤器函数?
或者,如果我完全错误,当我的目标是 1:让用户定义他们想要的任何过滤器时,我该如何调用我的 Filter
函数。 2:不允许用户更改我的源代码
更新 这可能没有我最初想象的那么困难。我创建了一个头文件,用户将在其中说出他们希望 Filter 类使用以下行调用哪个函数
//User types this into "FunctionImplementations.h"
#include "IIR.h"
typedef IIR FilterImplementation;
//then I just type
#include "FunctionImplementations.h"
FilterImplementation.filter(); //Implements IIR classes filter function
有几种方法可以实现这种多态性。
主要问题是需要编译时多态行为还是运行时多态行为。在第一种情况下,解决方案通常是定义一个函数(或类)模板来执行您的通用工作,并使用您的泛型代码要调用的可调用对象的类型对其进行参数化,以执行作业的自定义部分:
// This is how you would define your generic procedure
template<typename F> void do_something(F f, ...)
{
...
f(...);
...
}
// This is how you would use it...
void my_func(...) { ... };
do_something(&my_func, ...); // with a function pointer
do_something([] (...) { ... }, ...); // with a lambda
struct my_functor { operator void () (...) { ... } };
do_something(my_functor(), ...); // with a functor
如果定义自定义行为的对象类型仅在运行时确定,则有两种可能性:要么使用 std::function<>
封装回调,要么使用虚函数方法。我个人更喜欢前者,因为它不会仅仅为了实现动态多态性而强迫您创建继承层次结构。
以下是使用 std::function<>
对象的方式:
void my_func1(int, int) { ... }
void my_func2(int, int) { ... }
std::function<void(int, int)> fxn = &my_func1;
fxn(2, 3);
...
fxn = &my_func2;
fxn(3, 4);
...
fxn = [] (int x, int y) { ... };
fxn(4, 5)
您可以利用它来定义泛型过程:
void do_something(std::function<void(int, int)> f, ...)
{
...
f(3, 4);
...
}
此时,您可以使用可以分配给std::function
的任何内容(即具有兼容签名的任何可调用对象)调用do_something()
。
如果需要在编译时执行此操作,可以考虑使用模板而不是继承。举个例子:
template<typename Derived> // Derived is having DoActualWork
class WorkerBase
{
public:
DoWork()
{
((Derived*)this)->DoActualWork();
}
};
class MyWorker : public WorkerBase<MyWorker>
{
public:
void DoActualWork() {...}
};
在这里,MyWorker
继承类模板WorkerBase
将自身作为类型参数传递给模板。从 this
到 Derive
的转换是必需的,并且将起作用,因为此对象实际上是派生类。
请注意,这是使用类的编译时多态性技术之一。通过模板,您可能以其他方式拥有此类功能。 std::map
可以与std::greater
一起使用!
- WIN32:C++,为什么在WM_CLOSE上调用Messagebox函数程序正在冻结
- 为什么程序员同时使用 std::bad_alloc 和 std::exception.是否 std::例外 仅是不够的
- C++std::atomic在程序员级别保证了什么
- 如何检查程序员在C++中提供的两种不同格式的输入
- C++ 函数程序中的平均输出始终为 0.0
- 为什么 C++ 程序员更喜欢前缀 ++,而 Java 程序员更喜欢后缀 ++?
- 使用getline和字符串函数C++程序中的分段错误
- 如何理解哪个递归函数程序需要
- 程序员可以用 C++ 编写多少个嵌套结构
- 3 函数加主函数 C 程序计算和显示阶乘
- 如果/else语句未显示/可变分配问题的输出;初学者程序员
- 安装/理解c++库的问题(新手程序员)
- 在结构中嵌入函数程序集代码
- 初学者程序员 c++(局部与全局变量声明)
- 工资计算器(加班工资)需要高级程序员的帮助
- 是否有任何合理的场景,程序员可能希望避免布尔表达式的短路计算
- 面向C++程序员的 SQL 简介
- 视觉C++:我可以强制我的程序员为每个类定义复制构造函数吗?
- 为什么这个程序员特别通过引用在函数中传递指针?
- 如何使用函数指针或虚函数来允许其他程序员定义函数的实现?