有没有办法使用指针从任何类调用任何方法?
类似这样的事情:
#include <vector>
class AnyClass {
public:
virtual void call(void* instance, void (*callback)(float value), float value) = 0;
};
class MyClass1 : public AnyClass {
public:
// void call(void* instance, void ((void *)::*callback)(float value), float value)
void call(void* instance, void (*callback)(float value), float value)
{
MyClass1* obj = (MyClass1*)instance;
(obj->*(callback))(value);
}
void hello(float value)
{
printf("hello %f\n", value);
}
};
class MyClass2 : public AnyClass {
public:
void call(void* instance, void (*callback)(float value), float value)
{
MyClass2* obj = (MyClass2*)instance;
(obj->*(callback))(value);
}
void world(float value)
{
printf("world %f\n", value);
}
};
int main()
{
struct Caller {
AnyClass* instance;
void (*callback)(float value);
float value;
};
Vetcor<Caller> vetcor = { { new MyClass1, &MyClass1::hello, 0.123 }, { new MyClass2, &MyClass2::world, 0.456 } };
for (int i = 0; i < vetcor.size(); i++) {
vetcor[i].call(vetcor[i].instance, vetcor[i].callback, vetcor[i].value);
}
return 0;
}
目前我正在使用模板,但这非常烦人,因为我仅限于一个类,所以我必须为每个类创建一个向量。我希望能够有一个单一的向量,我可以在其中推送任何类的任何方法......
编辑: 我想避免太多代码,但为了给出上下文,这就是我现在解决问题的方法:
class Plugin {
public:
virtual float getValue(int valueIndex) = 0;
virtual void setValue(int valueIndex, float value) = 0;
virtual int getValueCount() = 0;
virtual const char* getValueKey(int valueIndex) = 0;
virtual int getValueIndex(const char* key) = 0;
};
template <typename T>
class Val {
protected:
T* instance;
float value_f;
public:
const char* key;
T& (T::*callback)(float value);
Val(T* instance, float initValue, const char* _key, T& (T::*_callback)(float value))
: instance(instance)
, value_f(initValue)
, key(_key)
, callback(_callback)
{
}
inline float get()
{
return value_f;
}
void set(float value)
{
value_f = range(value, 0.0, 1.0);
}
void call(float value)
{
(instance->*(callback))(value);
}
};
template <typename T>
class Mapping : public Plugin {
public:
std::vector<Val<T>*> mapping;
Mapping(std::vector<Val<T>*> mapping)
: mapping(mapping)
{
}
int getValueIndex(const char* key)
{
for (int i = 0; i < mapping.size(); i++) {
if (strcmp(mapping[i]->key, key) == 0) {
return i;
}
}
return -1;
}
int getValueCount()
{
return mapping.size();
}
float getValue(int valueIndex)
{
return mapping[valueIndex]->get();
}
void setValue(int valueIndex, float value)
{
mapping[valueIndex]->call(value);
}
const char* getValueKey(int valueIndex)
{
return mapping[valueIndex]->key;
}
};
class DemoClass : public Mapping<DemoClass> {
public:
Val<DemoClass> val1 = { this, 0.5, "VAL1", &DemoClass::setVal1 };
Val<DemoClass> val2 = { this, 0.0, "VAL2", &DemoClass::setVal2 };
DemoClass()
: Mapping({ &val1, &val2 })
{
}
// Do some stuff
DemoClass& setVal1(float value)
{
val1.set(value);
// Do some stuff
return *this;
}
DemoClass& setVal2(float value)
{
val2.set(value);
// do some stuff
return *this;
};
};
class AnotherClass : public Mapping<AnotherClass> {
public:
Val<AnotherClass> myVal = { this, 0.5, "MYVAL", &AnotherClass::setMyVal };
AnotherClass()
: Mapping({ &myVal })
{
}
AnotherClass& setMyVal(float value)
{
myVal.set(value);
// Do some stuff
return *this;
}
};
DemoClass
和 AnotherClass
是一些共享库,我使用 dlopen
加载它们。然后再次使用一些配置文件,我可以通过执行以下操作来设置值:obj.setValue(obj.getValueIndex("MYVAL"), 0.123)
。它工作完美,但在某些情况下,我觉得有一些限制(或者很可能缺乏一些 C++ 知识),但例如,如果我在 AnotherClass
上进行一些继承来定义一些额外的函数,那么它就会开始变得复杂。因此,如果我可以有一个指向对象的指针,然后有一个指向方法的指针,那么可以大大简化我的代码。但我可能相信这是不可能的......
尚不完全清楚您想要实现的目标,但这也许会指出一个有用的方向。
using Callback_t = std::function<void()>;
template <typename T>
Callback_t MakeCallback(void (T::*f)(float), float val) {
T* p = new T;
return [=]() { (p->*f)(val); }
}
std::vector<Callback_t> vetcor = {
MakeCallback(&MyClass1::hello, 0.123),
MakeCallback(&MyClass2::world, 0.456)};
for (int i = 0; i < vetcor.size(); i++) {
vetcor[i]();
}
这会泄漏
MyClass1
和 MyClass2
的实例,但你的示例也是如此。生命周期管理留给读者作为练习。