考虑以下模式:
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
}
其中 this
是 const Parent *
类型,这意味着 this->c
是 const Child &
。返回 Child &
违反了 const-ness。
getter 本身不修改对象,但它允许绕过调用者代码中的常量,如上面的代码所示。
关于c++ - 有没有一种方法可以使引用成为常量 setter/getter ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14533864/