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

adi*_*tin 20 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.
Run Code Online (Sandbox Code Playgroud)

.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.
Run Code Online (Sandbox Code Playgroud)

Lig*_*ica 33

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

这是一种确定的设计气味,你正在为了它而编写存取器.你真的需要它们吗?你真的需要为每个人进行低级公共"获取"和"设置"操作吗?这不太可能.

毕竟,如果您所做的只是为每个私有数据成员编写一个getter和一个setter,并且每个私有数据成员具有相同的逻辑,那么您可能只是公开了数据成员.

相反,你的班级应该有意义语义的操作,在他们的职责过程中,可能会或可能不会使用私人数据成员.您会发现每个有意义的操作都与其他操作完全不同,因此重复代码的问题就会被破坏.

正如纳米所说:

简单:避免访问者.编写你的课程来做一些事情,而不是拥有一些东西.

即使对于那些对它们没有任何帮助的操作,比如控制可见性,你应该有a bool isVisible() const,a void show()和a void hide().你会发现,当你开始这样编码的时候,它会促使人们远离模板"为了它"的吸气剂和制定者.

  • @black:为了它而使用OOP是好的,但是为了它而获得OOP _wrong_不是.:)是的,我知道这是他们在学校教授的方式(遗憾的是). (2认同)
  • 私有数据成员的公共setter/getter对比公共数据成员有一个很大的优势:您可以轻松地临时添加日志行或断点,并可以调试每个访问,而无需修改访问该属性的所有代码.通常人们不知道,10年后某个成员可以访问多少. (2认同)

Mat*_*son 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. 
}
Run Code Online (Sandbox Code Playgroud)

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

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

现在,我们可以实现ShowHide,Flash,Unflash,Shaded通过这样做,避免了各功能内重复等.

void Element::Show()
{
    UpdateProperty(visible, true);
}
Run Code Online (Sandbox Code Playgroud)

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

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

MoveTo成为:

void Element::MoveTo(Point p)
{
    UpdateProperty(position, p);
}
Run Code Online (Sandbox Code Playgroud)

根据之前未公开的信息进行编辑,添加到问题中:

显然,上述技术同样可以应用于执行此类工作的任何形式的函数:

void Element::SetVisible(bool value)
{
   UpdateProperty(visible, value);
}
Run Code Online (Sandbox Code Playgroud)

将起到与Show上述相同的作用.这并不意味着您可以远离声明函数,但它减少了对函数内部代码的需求.

  • @adigostin 受保护的方法通常是设计气味的标志。并非总是如此,但在大多数情况下,这意味着您正在使用继承进行实现共享。我认为这和对`setter` 的需求清楚地表明设计层面存在问题,例如错误的抽象层面。 (2认同)

eni*_*has 7

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

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

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