考虑以下模式:
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");
}
规范如下:
问题在于:
使用指针(使访问器返回Child*
)很容易实现这一点,但似乎有一个共识(并且理所当然地),建议引用是可取的,因为它们隐藏了指针的复杂性。 / p>
有什么办法吗?如果没有,我只会回到指针。
答案 0 :(得分:2)
如果返回的引用不是const,则调用者可以修改该对象,即使它在自己的上下文中是const:
const Parent p = ...
Child & child = p.GetChild(); // valid const call, invalid return type
但是,当您尝试返回属于类本身(它本身不是指针)的成员变量时,这只是问题。正如你已经建议的那样,让Child成为指针就行了。但是将非const指针返回到非指针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 &
会违反常量。
getter本身不会修改对象,但它允许绕过调用者代码中的常量,如上面的代码所示。
答案 1 :(得分:0)
要求看起来有冲突,因为如果不能修改Parent,那么即使Child成员也不应该被修改。
但如果您的规范被放宽并且可以修改Child成员对象,那么可能的解决方案是使用const_cast。
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 2: Doesn't compile, of course
int main()
{
Parent p = Parent();
Child& c = const_cast<Child &>(p.GetChild()); // No more Error
c.Foo = 'B';
std::cout << p.c.Foo << std::endl; // A, good
std::cout << c.Foo << std::endl; // B, good
system("PAUSE");
}