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

Wrapper for getter and setter methods in c++

本文关键字:包装 方法 setter getter c++      更新时间:2023-10-16

我有几个类有一对代表"setter"answers"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的速度大约是直接调用setter速度的18倍。速度在这里很重要,因为我需要在动画库中使用该机制(Animator将在不了解源对象的情况下设置属性)。

所以我的问题是:如何加快这个机制?有什么"行业标准"的方法吗?也许我应该使用经典的方法指针而不是std::函数?

您可以采用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;
};

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

演示

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

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