有没有办法从任何类调用方法指针

问题描述 投票:0回答:1

有没有办法使用指针从任何类调用任何方法?

类似这样的事情:

#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
上进行一些继承来定义一些额外的函数,那么它就会开始变得复杂。因此,如果我可以有一个指向对象的指针,然后有一个指向方法的指针,那么可以大大简化我的代码。但我可能相信这是不可能的......

c++ pointers
1个回答
1
投票

尚不完全清楚您想要实现的目标,但这也许会指出一个有用的方向。

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
的实例,但你的示例也是如此。生命周期管理留给读者作为练习。

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