考虑以下模式:
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*)来完成这一任务非常容易,但似乎有一种共识(而且是正确的),即引用是明智的,因为它们隐藏了指针的复杂性。
有什么办法吗?如果没有,我将回到指针。
发布于 2013-01-26 04:32:14
如果返回的引用不是const,则调用方可以修改对象,即使它在自己的上下文中是const:
const Parent p = ...
Child & child = p.GetChild(); // valid const call, invalid return type但是,这只是在试图返回作为类本身一部分的成员变量(它本身不是指针)时才会出现的问题。所以,正如你已经建议的,让这个孩子成为一个指针是可以的。但将非指针指针返回到非指针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本身并不修改对象,但它允许绕过调用方代码中的const-性,如上面的代码所示。
发布于 2013-01-26 05:24:42
需求看起来很矛盾,因为如果不能修改父级,那么就意味着即使是子成员也不应该被修改。
但是,如果您的规范比较宽松,并且可以修改子成员对象,那么可能的解决方案是使用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");
}https://stackoverflow.com/questions/14533864
复制相似问题