c ++中getter和setter方法的包装器

时间:2015-07-02 13:37:26

标签: c++

我的课程很少,有一对方法代表" 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() { ... }
}

我想创建一个名为PropertyAccess的类,它可以包装任何类的每对setter和getter。这将允许我通过此PropertyAccess转到其他对象,这些对象将能够调用那些没有任何关于ClassA或ClassB的知识的setter和getter。

这是我的意见:

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

我这样使用它:

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

一切正常,但这是极其缓慢的方法。通过PropertAccess调用setter比直接调用它们大约慢18倍。速度在这里很重要,因为我需要在动画库中使用该机制(Animator将在不知道源对象的情况下设置属性)。

所以我的问题是:如何加快这种机制?是否有任何&#34;行业标准&#34;方法呢?也许我应该使用经典方法指针而不是std :: function?

2 个答案:

答案 0 :(得分:2)

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

您当前的实施不仅速度慢,而且不安全。看看如果你做了会发生什么

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

答案 1 :(得分:1)

您可以采用Anton Slavin的解决方案并引入擦除对象类型的界面。它将使访问器的生命周期管理变得更加复杂(您将不得不使用引用/指针/智能指针并管理生命周期,因为您将无法复制访问器)并且在运行时将花费,因为虚拟方法调用将不会内联所以我会测量它是否比原始解决方案更快。

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