如何正确调用返回常量引用的类成员的 setter

How do I properly call setters on a return constant referenced class member

提问人:Xan Nava 提问时间:1/1/2017 最后编辑:Xan Nava 更新时间:1/1/2017 访问量:976

问:

我的问题是我试图访问类成员的常量引用的无常量setter,从而导致错误(C2662)。如果我使设置的值可变,并且 setter 保持不变,那么我没问题,但是我已经读到您应该避免这样做,但找不到其他方法来做到这一点。

vector2D的定义:

class vector2D {
    int _x;
    int _y;
public:
    vector2D() :
    _x(0),
    _y(0) {};

    // Getters
    int xGet() { return _x;};
    int yGet() { return _y;};

    // Setters
    void xSet(int x) {
        if (x > 100) {
            _x = 100;
            return;

        } else if (x < 0) {
            _x = 0;
            return;

        } else {
            _x = x;
            return;
        }
    };

    void ySet(int y) {
        if (y > 100) {
            _y = 100;
            return;

        } else if (y < 0) {
            _y = 0;
            return;

        } else {
            _y = y;
            return;
        }
    };
};

npc的定义:

class npc {
    vector2D _position;
public:
    npc () {};
    const vector2D& positionGet() const{
        return _position;
    };
};

main.cpp :

main () { 
    vector2D myPos;
    myPos.xSet(2);    //Okay

    npc myGuy;
    myGuy.positionGet().xSet(2);    //C2662

    return 0;
}

我试过什么:

我尝试使 xSet/ySet 常量函数,但这给了我一个错误(expresion 必须是可修改的左值),这是有道理的。我一直在阅读有关此的文章,但正确的方法从未真正清楚。

我尝试使 x/y 可变,然后这样我就可以使 setter 函数恒定,这确实消除了错误,但后来我读到很多人说不要使用可变的,还有什么其他方法可以做到这一点?

我还试图使“_position”的返回值不变,但这样做不是不安全吗???

注意:我也在努力使我的问题变得更好,所以请留言/发表评论,说明我如何才能提出更好的:D


编辑:我发现了什么

因此,很多人建议只是返回一个非常量的“_position”引用,但我发现的问题是您可以直接为返回的引用赋值。

vector2D newPos;
myGuy.positionGet() = newPos;

这很糟糕,因为返回的值是私有成员,因此不应直接分配。 这也很糟糕,因为如果 npc 通过引用传递给函数,然后完成上述操作,一旦 vector2D 超出范围,它就会调用 vector2D 上的析构函数。

void functTest (npc & ch1) {
    vector2D c1;
    ch1.positionGet() = c1;

    return;
}

出于某种原因,这也破坏了ch1._position ???

C++(英语:C++) 吸气机-setter 可变

评论

0赞 Oleg Bogdanov 1/1/2017
“我还试图使'_position'的返回值不变,但这样做不是不安全吗???”绝对可以返回非常量引用,这完全取决于您或用户之后将如何处理它
0赞 Xan Nava 1/1/2017
@OlegBogdanov谢谢!我想知道私有范围是否仍然保护它免受 myGuy.positionGet() = somePosition;如果我的程序试图破坏引用的对象,我也遇到了一个问题(我将尝试给出一个更好的例子,可能是因为我在意外 XD 上返回指向该对象的指针)

答:

1赞 Lightness Races in Orbit 1/1/2017 #1

如果你想让你的 getter 返回一个可变引用,那就这样做

您想要调用并获取可以修改的对象。positionGet()

所以不要成功!const

vector2D& positionGet() {
    return _position;
};

简单如。

评论

0赞 Xan Nava 1/1/2017
这安全吗?我的意思是您要返回私有成员“_position”的引用(内存地址)
0赞 Xan Nava 1/1/2017
比方说,私人是否仍然保护它免受伤害。myGuy.position.Get() = somePosition; ?
0赞 Lightness Races in Orbit 1/1/2017
@XanNava:没有。您正在制作一个函数,以允许世界访问此变量并更改它。因此,世界可以访问这个变量并改变它。你不能两全其美。
0赞 Xan Nava 1/1/2017
那么,使某些变量可变而使其他变量不可变,难道只会使可变部分可变,而返回一个非常量引用会使其他部分容易受到攻击吗?老实说,我是个菜鸟,但我喜欢尽我所能做每一件事,所以非常感谢你抽出时间。
0赞 Lightness Races in Orbit 1/1/2017
@XanNava:喝了一整瓶普罗赛克之后,我对你说的话的理解非常有限,但我最初的回答是:是的,这是真的,但是你应该在需要在上下文中可变的时候(例如互斥锁)来做东西,而不是因为你没有正确设计你的界面。如果你的 getter 应该返回对类的某些属性的可变引用,请不要这样做。这样做就是在撒谎。mutableconstconstconst
0赞 Edy 1/1/2017 #2

您可以为该位置提供可变接口和常量接口:

class npc {
    vector2D _position;
public:
    npc () {};
    const vector2D& position() const { return _position; };
    vector2D& mutable_position() { return _position; };
};

是的,当你调用 mutable_position() 时,将返回对私有成员的引用,但如果这是程序员的意图(如调用中明确使用“mutable_”所示),那么它应该没问题。