c++ - 有没有一种方法可以使引用成为常量 setter/getter ?

标签 c++ pointers reference pass-by-reference

考虑以下模式:

class Child
{
public:
    char Foo;

    Child(char foo)
    {
        Foo = foo;
    }
};

class Parent
{
public:
    Child c;

    Parent() : c('A') { }

    const Child& GetChild() const
    {
        return c;
    }
};

// Scenario 1: Works, but useless
int main()
{
    Parent p = Parent();
    Child c = p.GetChild();
    c.Foo = 'B';
    cout << p.c.Foo << endl; // A, wrong
    cout << c.Foo << endl; // B, good
    system("PAUSE");
}

// Scenario 2: Doesn't compile, of course
int main()
{
    Parent p = Parent();
    Child& c = p.GetChild(); // Error
    c.Foo = 'B';
    cout << p.c.Foo << endl; // A, good
    cout << c.Foo << endl; // B, good
    system("PAUSE");
}

规范如下:

  • getter必须定义为const(因为它不修改Parent)
  • getter给出的引用必须修改底层的值

问题在于:

  • 如果 getter 本身是 const,C++ 要求 getter 的返回值是 const(为什么?)
  • C++ 禁止将 const 值分配给引用(逻辑上)

使用指针很容易实现这一点(使访问器返回 Child*),但似乎有一个共识(而且理所当然)认为引用是可取的,考虑到它们隐藏了复杂性的指针。

有什么办法吗?如果没有,我将恢复为指针。

最佳答案

如果返回的引用不是 const,调用者可以修改对象,即使它在自己的上下文中是 const:

const Parent p = ...
Child & child = p.GetChild(); // valid const call, invalid return type

但是,这只是当您尝试返回属于类本身的成员变量(它本身不是指针)时才会出现的问题。所以正如你已经建议的那样,让 Child 成为一个指针就可以了。但是将非常量指针返回到非指针 Child 会导致同样的问题...

为了更好地说明问题,考虑这个内存布局图:

Parent:  [Child]

Child:   [char ]

所以父对象只包含一个 Child 对象,所以修改 Parent 实例会修改 Child 实例,同时修改 Parent::c 修改 Parent 本身。

所以你不能返回指针或对非 const 对象的引用(this 指针在 const 成员函数中指向的对象):

Child& GetChild() const
{
    return c;    // compiler will complain here
}

等于:

Child& GetChild() const
{
    return this->c;   // compiler will complain here
}

其中 thisconst Parent * 类型,这意味着 this->cconst Child &。返回 Child & 违反了 const-ness。

getter 本身不修改对象,但它允许绕过调用者代码中的常量,如上面的代码所示。

关于c++ - 有没有一种方法可以使引用成为常量 setter/getter ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14533864/

相关文章:

c++ - 数据文件输入/输出错误

Python ctypes - dll 函数接受结构崩溃

C 结构体值在函数内部和外部不同

java - R.java 包含错误的资源指针

rust - 在模式匹配中借用

c++ - 删除 std::map (Visual C++)

c++ - 避免在默认模板中使用尖括号

Java 按值传递——你能解释一下吗?

c++ - 结构名称不隐藏变量名称

c++ - 如何检查引用是否为 const?