简体   繁体   English

包装用于C ++中的getter和setter方法

[英]Wrapper for getter and setter methods in c++

I have few classes with pair of methods which stands for "setter" and "getter" methods, like: 我有几个带有一对方法的类,分别代表“ setter”和“ getter”方法,例如:

class ClassA
{
    void SetSomeProperty(const int& value) { ... }
    int GetSomeProperty() { ... }

    void SetAnotherProperty(const Vec3& value) { ... }
    Vec3 GetAnotherProperty() { ... }
};

class ClassB
{
    void SetColor(const Vec4& value) { ... }
    Vec4 GetColor() { ... }
}

I want to create a class called PropertyAccess that can wrap each pair of setter and getter of any class. 我想创建一个名为PropertyAccess的类,该类可以包装任何类的每对设置器和获取器。 This will allow me to past this PropertyAccess to other object which will be able to call those setters and getters wihout any knowledgne about ClassA or ClassB. 这将允许我将此PropertyAccess传递到其他对象,该对象将无需了解ClassA或ClassB即可调用那些设置方法和获取方法。

this is my iplementation: 这是我的实现:

class PropertyAccess
{
public:
    template <typename TClass, typename TType> using SetterPointer = void (TClass::*)(const TType&);
    template <typename TClass, typename TType> using GetterPointer = TType(TClass::*)();

    template <typename TClass, typename TType>
    PropertyAccess(
        TClass* object,
        SetterPointer<TClass, TType> setter,
        GetterPointer<TClass, TType> getter)
    {
        using std::placeholders::_1;
        m_setter = new Setter<TType>(std::bind(setter, object, _1));
        m_getter = new Getter<TType>(std::bind(getter, object));
    }

    ~PropertyAccess()
    {
        delete m_setter;
        delete m_getter;
    }

    template <typename T>
    void Set(const T& value)
    {
        ((Setter<T>*)m_setter)->m_setter(value);
    }

    template <typename T>
    T Get()
    {
        return ((Getter<T>*)m_getter)->m_getter();
    }

private:
    struct Base
    {
        virtual ~Base() {}
    };

    template <typename TType>
    struct Setter : public Base
    {
        Setter(std::function < void(const TType&) > setter) { m_setter = setter; }

        std::function < void(const TType&) > m_setter;
    };

    template <typename TType>
    struct Getter : public Base
    {
        Getter(std::function < TType() > getter) { m_getter = getter; }

        std::function < TType() > m_getter;
    };

    Base* m_setter;
    Base* m_getter;
};

I use it like that: 我这样使用它:

ClassA a;
PropertyAccess p(&a, &ClassA::SetSomeProperty, &ClassA::GetSomeProperty);
p.Set<int>(10);
int v = p.Get<int>();

Everything works fine, but this is exteremly slow approach. 一切正常,但是这是极慢的方法。 Calling setters through PropertAccess is approx 18 times slower than call them directly. 通过PropertAccess调用设置程序的速度比直接调用设置程序的速度慢约18倍。 Speed is important here, because I need to use that mechanism in animation library (Animator will set properties without knowledge about source objects). 速度在这里很重要,因为我需要在动画库中使用该机制(Animator会在不了解源对象的情况下设置属性)。

So my question is: how to speed up this mechanism? 所以我的问题是:如何加快这种机制? Is there any "industry standard" approach for that? 是否有任何“行业标准”方法? Maybe I should use classic method pointers instead of std::function? 也许我应该使用经典的方法指针而不是std :: function?

Make PropertyAccess itself a template: 使PropertyAccess本身成为模板:

template <typename TClass, typename TType>
class PropertyAccess
{
public:
    using SetterPointer = void (TClass::*)(const TType&);
    using GetterPointer = TType(TClass::*)();

    PropertyAccess(TClass* object, SetterPointer setter, GetterPointer getter)
        : m_object(object), m_setter(setter), m_getter(getter)
    {
    }

    void Set(const TType& value) {
        (m_object->*m_setter)(value);
    }

    TType Get() {
        return (m_object->*m_getter)();
    }

private:

    TClass* m_object;
    SetterPointer m_setter;
    GetterPointer m_getter;
};

Demo 演示版

Your current implementation is not only slow, it's unsafe. 您当前的实现不仅缓慢,而且不安全。 See what happens if you do 看看你会怎么做

ClassA a;
PropertyAccess p(&a, &ClassA::SetSomeProperty, &ClassA::GetSomeProperty);
p.Set<double>(10); // but property is int

You can take Anton Slavin's solution and introduce an interface to erase object type. 您可以采用Anton Slavin的解决方案,并引入一个接口来擦除对象类型。 It will make lifetime management of accessors more complicated (you'll have to use references/pointers/smart pointers and manage lifetime because you won't be able to copy accessors) and will cost at runtime as virtual method calls will not inline so I would measure if it is quicker than your original solution. 这将使访问器的生命周期管理变得更加复杂(您将不得不使用引用/指针/智能指针并管理生命周期,因为您将无法复制访问器),并且由于虚拟方法调用无法内联,因此在运行时会产生成本将测量它是否比原始解决方案更快。

template<typename TType>
struct PropertyAccess
{
    virtual void Set(const TType& value) = 0;
    virtual TType Get() = 0;
};

template <typename TClass, typename TType>
class PropertyAccessT : public PropertyAccess<TType>
{
public:
    using SetterPointer = void (TClass::*)(const TType&);
    using GetterPointer = TType(TClass::*)();

    PropertyAccessT(TClass* object, SetterPointer setter, GetterPointer getter)
        : m_object(object), m_setter(setter), m_getter(getter)
    {
    }

    void Set(const TType& value) {
        (m_object->*m_setter)(value);
    }

    TType Get() {
        return (m_object->*m_getter)();
    }

private:

    TClass* m_object;
    SetterPointer m_setter;
    GetterPointer m_getter;
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM