C ++ Get / Set访问器 - 如何避免键入重复代码?

时间:2015-11-29 13:38:44

标签: c++

我正在写一个非常大的图书馆,我发现自己一直在编写几乎相同的访问者。我已经有了几十个访问器,如下面的那个。

问题:如何声明/实现访问器以保存键入所有这些重复代码? (请不要#defines;我正在寻找C ++结构。)

更新:是的,我需要访问器函数,因为我需要指向这些访问器以获取名为Property Descriptors的东西,这可以大大节省我的GUI代码(非库)。

.h文件

private:
    bool _visible;
public:
    bool GetVisible() const { return _visible; }
    void SetVisible (bool value);

// Repeat for Get/SetFlashing, Get/SetColor, Get/SetLineWidth, etc.

.cpp文件

void Element::SetVisible (bool value)
{
    _visible = value;
    this->InvalidateSelf(); // Call method in base class
    // ...
    // A bit more code here, identical in 90% of my setters.
    // ...
}

// Repeat for Get/SetFlashing, Get/SetColor, Get/SetLineWidth, etc.

4 个答案:

答案 0 :(得分:33)

  

我发现自己一直在编写几乎相同的访问者。我已经有了几十个访问器,如下面的那个。

这是一种确定的设计气味,你正在编写存取器"为了它"。你真的需要它们吗?你真的需要一个低水平的公众"得到"和"设置"每个人的手术?这不太可能。

毕竟,如果您正在为每个私有数据成员编写一个getter和setter,并且每个私有数据成员具有相同的逻辑,那么您也可以公开数据成员。

相反,您的类应该具有有意义的语义操作,这些操作在其职责过程中可能会或可能不会使用私有数据成员。您会发现每个有意义的操作都与其他操作完全不同,因此重复代码的问题就会被解决。

早上好表示:

  

简单:避免访问者。编写你的课程来做某事,而不是做点什么。

即使对于那些对他们没有任何帮助的操作,例如控制可见性,您应该有bool isVisible() constvoid show()void hide()。你会发现,当你开始这样的编码时,它会促使人们远离模板,而不是为了它#34;吸气剂和setter方法。

答案 1 :(得分:26)

虽然我认为Lightness Races in Orbit是一个非常好的观点,但也有一些方法可用于实现"重复代码",可以应用,假设我们确实有一个类有许多相似的东西需要单独控制,所以继续这样,说我们有几个这样的方法:

void Element::Show()
{
   visible = true;
   Invalidate();
   // More code goes here. 
}

void Element::Hide()
{
   visible = false;
   Invalidate();
   // More code goes here. 
}

现在,在我看来,这打破了DRY(不要重复自己)的原则,所以我们应该这样做:

void Element::UpdateProperty(bool &property, bool newValue)
{
   property = value;
   Invalidate();
   // More code goes here. 
}

现在,我们可以通过这样做来实现ShowHideFlashUnflashShaded等,避免在每个功能中重复。

void Element::Show()
{
    UpdateProperty(visible, true);
}

如果类型不是bool,例如有一个position,我们可以这样做:

template<typename T>void Element::UpdateProperty(T &property, T newValue)
{
   property = value;
   Invalidate();
   // More code goes here. 
}

并且MoveTo变为:

void Element::MoveTo(Point p)
{
    UpdateProperty(position, p);
}

编辑根据以前未公开的信息添加到问题:

显然,上述技术同样适用于执行此类工作的任何形式的功能:

void Element::SetVisible(bool value)
{
   UpdateProperty(visible, value);
}

将与上述Show一样有效。它并不意味着您可以放弃声明函数,但它减少了对函数内部代码的需求。

答案 2 :(得分:7)

我同意Lightness。你应该为手头的任务设计你的课程,如果你需要这么多的getter和setter,你可能会做错事。

也就是说,大多数好的IDE都允许你生成简单的getter和setter,有些甚至可以让你自定义它们。您可以将重复代码保存为模板,并在需要时选择代码片段。

您还可以使用emacs和Vim(使用Ultisnips)等可自定义的编辑器,并创建一些自定义帮助功能,以使您的工作轻松。自动化的任务已经成熟。

答案 3 :(得分:0)

你应该用任何语言编写get / set函数集的唯一时间是它是否只是读取或写入一个简单变量;如果你所做的一切都让人们更难阅读,那么就不要费心包办对数据的访问。如果这就是您正在做的事情,请停止做任何事情。

如果您确实需要一组get / set函数,请不要调用它们来获取和设置 - 使用赋值和类型转换(并巧妙地执行)。这样,您可以使代码更具可读性,而不是更少。

这非常不优雅:

class get_set {
    int value;
public:
    int get() { return value; }
    void set(int v) { value = v; }
};

这好一点

class get_set_2 {
     value_type value;
     bool needs_updating;
 public:
    operator value_type const & () {
        if (needs_updating) update(); // details to be found elsewhere
        return value;
    }

    get_set_2& operator = (value_type t) {
        update(t); // details to be found elsewhere
        return *this;
    }
};

如果您没有采用第二种模式,请不要做任何事情。