【问题标题】:How to avoid having to write boilerplate accessor code如何避免编写样板访问器代码
【发布时间】:2016-05-24 10:15:43
【问题描述】:

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

class A
{
  int x;

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

实现访问器的整个想法围绕着能够拦截对它们的读写访问。我偶然发现了this 库(我不是作者)。这真的让我想知道,如果为了避免编写样板代码,可以/应该只写如下内容:

class A
{
public:
  property<int> x;

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

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

【问题讨论】:

  • 这是基于意见的,但是如果您在您提供的链接中查看property 的实现,您会发现它增加了很多开销......如果您这样做可能没问题正在构建 UI,但如果您正在做一些核心编程,则不会。另外,在我(主观)看来,如果你在任何地方都重载了operator=,就更难阅读代码了。
  • 我并没有特别提到这个库,这只是一个例子,property&lt;&gt; 的实现是任意的。
  • 为什么首先需要所有这些 getter 和 setter?序列化?
  • @user1095108 “使用访问器而不是直接公开类的字段”有很好的论据,但通常都没有必要,许多人认为这是一种反模式。如果有一些真正的程序逻辑(例如带有一些验证的设置器),我不会将其视为样板。
  • @mkluwe 同意。此外,由于POLA,将具有真实程序逻辑的函数命名为 getX() 或 setX() 是一个坏主意。

标签: c++ getter-setter boilerplate


【解决方案1】:

有一些讨论 herethere 关于 getter 和 setter 是否一般都是邪恶的。

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

另外,请阅读有关“告诉-不要-询问”的内容,例如来自Martin Fowler

【讨论】:

    【解决方案2】:

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

    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函数应该很容易。

    【讨论】:

    • 问题有点宽泛 :),我并不是真的要求实现。
    • 好吧,那我误解你了——我不知道特殊的“技术”,而不是像这样编写一个简单的模板类并重用它......
    猜你喜欢
    • 2011-03-22
    • 1970-01-01
    • 1970-01-01
    • 2016-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多