定义非const'get'成员函数的原因? [英] Reasons for defining non-const 'get' member functions?

查看:68
本文介绍了定义非const'get'成员函数的原因?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在与Stroustrup的(编程原理和使用C ++的实践)书一起学习C ++。在练习中,我们定义一个简单的结构:

I'm working on learning C++ with Stroustrup's (Programming Principles & Practice Using C++) book. In an exercise we define a simple struct:

template<typename T>
struct S {
  explicit S(T v):val{v} { };

  T& get();
  const T& get() const;

  void set(T v);
  void read_val(T& v);

  T& operator=(const T& t); // deep copy assignment

private:
  T val;
};

然后要求我们定义一个const和一个非const成员函数以获取 val

We're then asked to define a const and a non-const member function to get val.

我想知道:在任何情况下,使用非常量是否有意义get 函数返回 val

I was wondering: Is there any case where it makes sense to have non-const get function that returns val?

在这种情况下不能间接改变价值。在某些情况下,您需要一个const和一个非const get 函数来返回一个成员变量?

It seems much cleaner to me that we can't change the value in such situations indirectly. What might be use cases where you need a const and a non-const get function to return a member variable?

推荐答案

非常量获取器?

字母和字母设置器只是惯例。有时提供一个习惯用法,而不是提供一个getter和setter方法,而是按照

Getters and setters are merely convention. Instead of providing a getter and a setter, a sometimes used idiom is to provide something along the line of

struct foo {
    int val() const { return val_; }
    int& val() { return val_; }
private:
    int val_;
};

根据实例的恒定性,您可以得到引用或副本:

Such that, depending on the constness of the instance you get a reference or a copy:

void bar(const foo& a, foo& b) {
    auto x = a.val(); // calls the const method returning an int
    b.val() = x;      // calls the non-const method returning an int&
};

总体而言,这是否是一种好风格是一个见解。在某些情况下会引起混乱,而在其他情况下,这种行为正是您所期望的(见下文)。

Whether this is good style in general is a matter of opinion. There are cases where it causes confusion and other cases where this behaviour is just what you would expect (see below).

在任何情况下,设计根据类的用途以及您想如何使用它的接口,而不是盲目地遵循有关setter和getter的约定(例如,应给该方法一个有意义的名称,该名称表示它的作用,而不仅限于假装被封装,现在让我可以通过getter访问所有内部组件,这就是在各处使用getter的实际含义。)

In any case, it is more important to design the interface of a class according to what the class is supposed to do and how you want to use it rather than blindly following conventions about setters and getters (eg you should give the method a meaningful name that expresses what it does, not just in terms of "pretend to be encapsulated and now provide me access to all your internals via getters", which is what using getters everywhere actually means).

具体示例

考虑到容器中的元素访问通常是这样实现的。作为一个玩具示例:

Consider that element access in containers is usually implemented like this. As a toy example:

struct my_array {
    int operator[](unsigned i) const { return data[i]; }
    int& operator[](unsigned i) { return data[i]; }
    private:
        int data[10];
};

向用户隐藏元素不是容器的工作(即使数据可以是公开的)。您不希望根据要读取或写入元素的方式使用不同的方法来访问元素,因此在这种情况下,提供 const 和非const重载是很有意义的。

It is not the containers job to hide the elements from the user (even data could be public). You dont want different methods to access elements depending on whether you want to read or write the element, hence providing a const and a non-const overload makes perfectly sense in this case.

get与封装中的非常量引用

也许不是那么明显,但是提供getter和setter支持封装还是相反,都存在争议。虽然一般而言,此问题在很大程度上是基于意见的,但对于返回非const引用的获取者,与其说意见无关,不如说是。他们确实破坏了包围。考虑

Maybe not that obvious, but it is a bit controversial whether providing getters and setters supports encapsulation or the opposite. While in general this matter is to a large extend opinion based, for getters that return non const references it is not so much about opinions. They do break encapuslation. Consider

struct broken {
    void set(int x) { 
        counter++;
        val = x;
    }
    int& get() { return x; }
    int get() const { return x; }
private:
    int counter = 0;
    int value = 0;
};

顾名思义,此类已中断。客户只需获取参考即可,而该类没有机会计算修改值的次数(如 set 所示)。一旦返回非const引用,则有关封装的信息与公开成员几乎没有什么区别。因此,这仅用于自然行为(例如容器)的情况。

This class is broken as the name suggests. Clients can simply grab a reference and the class has no chance to count the number of times the value is modified (as the set suggests). Once you return a non-const reference then regarding encapsulation there is little difference to making the member public. Hence, this is used only for cases where such behaviour is natural (eg container).

PS

请注意,您的示例返回 const T& 而不是值。这对于模板代码是合理的,因为在模板代码中您不知道副本的价格,而对于 int 而言,返回 const int& 而不是 int 。为了清楚起见,我使用了非模板示例,尽管对于模板代码,您可能宁愿返回 const T&

Note that your example returns a const T& rather than a value. This is reasonable for template code, where you dont know how expensive a copy is, while for an int you wont gain much by returning a const int& instead of an int. For the sake of clarity I used non-template examples, though for templated code you would probably rather return a const T&.

这篇关于定义非const'get'成员函数的原因?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆