如何避免编写样板访问器代码

时间:2016-05-24 10:15:44

标签: c++ getter-setter boilerplate

我发现,在编写C ++代码时,我花了很多时间编写访问器样板代码,例如:

class A
{
  int x;

public:
  auto x();
  void set_x(decltype(x));
};

实现访问器的整个想法围绕能够拦截对它们的读写访问。我偶然发现了https://github.com/d-max/spots-dialog图书馆(我不是作者)。它真的让我想知道,如果,为了避免编写样板代码,可以/应该只写下这样的东西:

class A
{
public:
  property<int> x;

  A() {
    x.setter([this](int){ /* setter code */ });
  }
};

我的问题是:有哪些技术可以避免为getter和setter编写大量的样板代码?

2 个答案:

答案 0 :(得分:1)

关于吸气剂和制定者是否一般都是邪恶的,有一些讨论full Java demohere

所以,我避免使用样板代码的策略:尽量避免使用getter和setter。当需要一些纯数据类时,我将(少数)字段声明为public。但在这些情况下,我尽量避免给他们任何其他逻辑,我尽量保持这些类。

另外,请阅读tell-not-ask,例如来自there

答案 1 :(得分:0)

我猜你正在寻找这样的东西:

template <typename T>
class Property{
    private:

    T val;

    std::function<void(T& v,const T& newV)> setFN = nullptr;

    public:

    void setter(decltype(setFN) newSetter){
        setFN = newSetter;
    }

    void set(const T& newVal){
        if(!setFN)
            val = newVal;
        else
            setFN(val,newVal);
    }

    T get(){
        return val;
    }
};

所以基本上是一个模板类,它能够存储一个setter函数。如果存储了一个,则调用它,如果不存在,则仅使用operator=(当然需要由T定义)。

用法:

int main() {

    Property<int> x;

    x.set(5);
    std::cout << x.get() << std::endl;

    x.setter([](int& v, const int& newV){std::cout << "Setter called\n"; v=newV;});

    x.set(2);
    std::cout << x.get() << std::endl;

    return 0;
}

输出:

5
Setter called
2

Try it online

以类似的方式实现getter功能很容易。