如何禁用 getter 返回的临时写入?

LoP*_*TaL 5 c++

我有一个 getter,它返回一个临时对象,即内部对象的副本。

类似于以下内容:

class Foo
{
public:
    QString name() {return m_name;}
    void setName(const QString &name);
private:
    QString m_name;
}
Run Code Online (Sandbox Code Playgroud)

setter/getter 的预期用途是获取数据name()并通过设置数据setName()

但有时,错误地,我倾向于执行以下操作:

name().clear();
Run Code Online (Sandbox Code Playgroud)

或者直接对 getter 的返回进行一些其他修改。

请注意,上述行(以及类似的修改)的目的是清除 Foo,而不是临时变量,因此上面的行可以正确编译,但行为不正确,因为它将清除临时成员,而不是 Foo 的成员。

如何禁用这种不正确的用法,并在编译时出错?

请注意,我可能同时拥有第三方类型(我无法修改,例如 std::string 或上面的 QString)和自定义类型(我可以为此修改)。

编辑:

需要注意的是超载const&&&或类似的是没有用的,因为我可能是这样的:

Foo foo;
foo.name().clear();
Run Code Online (Sandbox Code Playgroud)

无论您选择什么重载,它都会编译得很好。

此外,对内部成员的所有修改都必须经过setName(),因为它会应用一些逻辑并通知其他一些对象,因此必须避免任何不是通过接口进行的修改。这可以防止 getter 通过非常量引用返回以允许上述用法或将私有成员设为公共成员。

Pic*_*ent 5

也许试试

const QString name() const {return m_name;}
Run Code Online (Sandbox Code Playgroud)

这将阻止直接使用:

foo.name().clear();
Run Code Online (Sandbox Code Playgroud)

另请注意,如评论中下划线所示,由于返回的 QString 是副本foo.name().clear();不会修改foo.m_name. 但是,是的,快速阅读代码可能会令人困惑。


编辑额外读取:when-use-const-3-return-types


一个更复杂的解决方案,灵感来自关于 getter-and-setter想法,将是

class Foo {
   
  public:
    ... 

    const QString& name() const & {return m_name;}   
    QString name() && {return std::move(m_name);}

  private:
    QString m_name;         
};
Run Code Online (Sandbox Code Playgroud)

另请注意,该博客文章鼓励使用这样的简单解决方案:

class Foo {
  ... 
  public
    QString name;         
};
Run Code Online (Sandbox Code Playgroud)

当您不必在“setter”方法中强制执行某些不变量或执行某些其他操作时,这是一种经济且可行的解决方案。