【问题标题】:Can I use const references instead of getter functions?我可以使用 const 引用而不是 getter 函数吗?
【发布时间】:2016-03-17 01:48:44
【问题描述】:

我只是想知道如果我只允许一个 const 引用变量,是否可以绕过使用 getter,如下所示

#include <string>

class cTest
{
    private:
        int m_i;
        std::string m_str;

    public:
        const int & i;
        const std::string & str;

    cTest(void)
    : i(m_i)
    , str(m_str)
    {}
};

int main(int argc, char *argv[])
{
    cTest o;
    int i = o.i; // works
    o.i += 5; // fails
    o.str.clear(); // fails

    return 0;
}

我想知道为什么人们似乎根本不这样做。我缺少一些严重的缺点吗?请提供优点和缺点列表,并在必要时进行更正。

优点:

  1. 调用 getter 函数没有开销。
  2. 由于功能较少,程序大小减小。
  3. 我仍然可以修改类的内部,引用变量提供了一个抽象层。

缺点:

  1. 我有一堆参考资料,而不是 getter 函数。这会增加对象大小。
  2. 使用const_cast,人们可以搞砸私人成员,但这些人很淘气,对吧?

【问题讨论】:

    标签: c++ reference getter


    【解决方案1】:

    确实有一些严重的缺点(除了您还提到的第二个缺点,我也将其归为“严重”类别):

    1) 您需要提供(并因此维护)一个复制构造函数:编译器默认值将不起作用。

    2) 您需要提供一个赋值运算符:编译器默认设置不起作用。

    3) 仔细考虑实现移动语义。同样,编译器默认值将不起作用。

    这三件事意味着您提出的const 参考反模式是行不通的。不要这样做!

    【讨论】:

    • 更不用说有一天您想要对数据使用更有效的表示,而您却不能,因为您需要对这些类型的有效引用。
    • @chris:这是一个很好的观点。即使您有一个返回 const ref 的函数,您也可以随时重构它以在您的数据模型发生变化时返回一个值副本。
    【解决方案2】:

    getter 函数的一个优点是您可能在某个时间点 - 想要更改返回值 - 如果没有 getter 函数,您将无法做到。这个场景实际上需要你返回非引用,这在 c++ 中不太常见。 [编辑] 但使用移动语义而不是引用,这应该是可行的[/编辑]

    您可能还想在 getter 函数中放置一个断点以了解谁在读取它的值,您可能想添加日志记录等。这称为 封装。

    getter 的另一个优点是,在调试版本中,您可以对返回的数据添加额外的检查/断言。

    最终编译器将内联您的 getter 函数,这将产生与您建议的代码相似的代码。

    一些额外的缺点:

    1) 模板代码将希望使用函数调用来获取值,即。 size(),如果您将其更改为 const& 变量,那么您将无法在某些模板中使用它。所以这是一个一致性问题。

    【讨论】:

      【解决方案3】:

      如果您想避免 getter 和 setter,使用 const 引用成员不是解决方案。

      相反,您需要确保周围结构的 const 正确性(这会自动为您提供对成员的 const 访问权限),并让成员成为逻辑上需要的任何成员。

      请务必阅读 getter 和 setter 何时可以、应该或可以与公共数据成员进行切换。参见例如this question。请注意,如果您更改接口,setter/getter 的显着优势是调用 getter 不会影响调用站点。现实似乎另有说法,例如对于任何自尊的 C++ 代码编辑器来说,重构一个成员及其所有访问点都是一项微不足道的操作。

      虽然有人可能会主张封装,但我更强烈主张 const 的正确性,这减少了对大量封装的需求,并且确实大大简化了代码。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-03-10
        • 1970-01-01
        • 2019-08-12
        • 2014-11-18
        • 2020-08-21
        • 2017-11-02
        相关资源
        最近更新 更多