gpt4 book ai didi

Is there a way to call method pointer from any class(有没有办法从任何类调用方法指针)

转载 作者:bug小助手 更新时间:2023-10-25 10:37:49 26 4
gpt4 key购买 nike



Is there a way to call any method from any class using pointer?

有没有一种方法可以使用指针从任何类调用任何方法?


Something like that:

大概是这样的:


#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;
}

For the moment I am using template, but it's super annoying cause I am restricted to one class, so I have to create a vector per class. I would love to be able to have a single vector where I can push any method of any class...

目前我使用的是模板,但它非常烦人,因为我被限制在一个类中,所以我必须为每个类创建一个向量。我希望能够有一个单一的向量,在那里我可以推送任何类的任何方法……


Edit:
I wanted to avoid to much code, but to give the context, this is how I solve my problem right now:

编辑:我想避免太多代码,但为了给出上下文,以下是我现在解决问题的方法:


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 and AnotherClass are some shared library and I load them using dlopen. Then again using some config file, I can set value by doing something like: obj.setValue(obj.getValueIndex("MYVAL"), 0.123). It work perfectly, but in some case I feel like some limitation (or most likly lacking some C++ knowledge), but for example if I do some inheritance on AnotherClass to define some extra function, then it's start to get complicated. So somehow, if I could have a pointer on an object and then a pointer to a method, it could simplify a lot my code. But I might beleive that it not possible...

DemoClass和AnotherClass是一些共享库,我使用dlopen加载它们。然后再次使用一些配置文件,我可以通过执行如下操作来设置值:obj.setValue(obj.getValueIndex(“MYVAL”),0.123)。它工作得很好,但在某些情况下,我感觉有一些限制(或者最有可能是缺乏一些C++知识),但例如,如果我对另一个类进行一些继承来定义一些额外的函数,那么它就会开始变得复杂。因此,不知何故,如果我可以先将指针指向对象,然后再将指针指向方法,这可以简化我的代码。但我可能会认为这是不可能的。


更多回答

You might want to take a look at std::variant which can hold multiple types.

您可能想看看std::Variant,它可以包含多种类型。

vetcor[i].call(...) I'm not sure I understand. struct Caller doesn't have a member named call. That said, my guess is you are looking for std::function. The search term for future research is "type erasure".

vetcor[i].call(.)我不太明白。struct Caller没有名为call的成员。也就是说,我猜你正在寻找std::function。未来研究的搜索词是“类型擦除”。

std::variant is very interresting, the problem seem that I still need to assign the type of the different variant upfront... But how can I do if I don't know them. I am loading my object using dlopen, the only thing I know is the virtual class they are inheriting from.

Std::Variant非常有趣,问题似乎仍然需要预先指定不同的Variant的类型……但如果我不认识他们,我怎么做呢?我使用dlopen加载我的对象,我唯一知道的是它们继承的虚拟类。

Why does it have to be without using templates?

为什么必须不使用模板?

Because right now I am using template and I am limited to the type I defined in the template. However, if there is way to pass to the template a generic type, I am also fine with it ;-)

因为现在我正在使用模板,并且我被限制为我在模板中定义的类型。但是,如果有办法将泛型类型传递给模板,我也不介意;-)

优秀答案推荐

It is not entirely clear what you are trying to achieve, but perhaps this would point in a useful direction.

目前还不完全清楚你试图实现的目标,但这或许会为你指明一个有用的方向。


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]();
}

This leaks instances of MyClass1 and MyClass2, but so does your example. Lifetime management is left as an exercise for the reader.

这会泄漏MyClass1和MyClass2的实例,但您的示例也会泄漏。终身管理是留给读者的练习。


更多回答

Woooow, amazing!! I think this can help me a lot ;-)

哇,太棒了!!我认为这对我有很大帮助;-)

Shouldn't this call delete or something? I see new and no delete.

这个调用不是应该删除什么的吗?我看到了新的,没有删除。

If we call delete the the annoymous function will not be able to call anymore the method. We should only delete the object once we don't need it anymore. We could eventually call delete in the annoymous function, but all depends what you want to achieve...

如果我们调用Delete,讨厌的函数将不能再调用该方法。我们只应在不再需要该对象时将其删除。我们最终可以在讨厌的函数中调用Delete,但这取决于您想要实现什么……

@JanSchultke Well, something somewhere should call delete. I didn't understand the OP's design well enough to decide what and where. I replicated the original example, leaks and all. I made a note of this below my code; I suppose you haven't looked that far down.

@JanSchultke嗯,某个地方应该叫Delete。我不能很好地理解行动的设计,无法决定要做什么和在哪里。我复制了原始的例子,泄密和所有的东西。我在我的代码下面记下了这一点;我想您还没有往下看那么远。

return [val]() { /*static*/T t; (t.*f)(val); } would avoid memleak.

返回[val](){/*静态*/T t;(t.*f)(Val);}可以避免内存泄漏。

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com