我在确定const在特定情况下的确切应用方式时遇到了一些麻烦.这是我的代码:
struct Widget
{
Widget():x(0), y(0), z(0){}
int x, y, z;
};
struct WidgetHolder //Just a simple struct to hold four Widgets.
{
WidgetHolder(Widget a, Widget b, Widget c, Widget d): A(a), B(b), C(c), D(d){}
Widget& A;
Widget& B;
Widget& C;
Widget& D;
};
class Test //This class uses four widgets internally, and must provide access to them externally.
{
public:
const WidgetHolder AccessWidgets() const
{
//This should return our four widgets, but I don't want anyone messing with them.
return WidgetHolder(A, B, C, D);
}
WidgetHolder AccessWidgets()
{
//This should return our four widgets, I don't care if they get changed.
return WidgetHolder(A, B, C, D);
}
private:
Widget A, B, C, D;
};
int main()
{
const Test unchangeable;
unchangeable.AccessWidgets().A.x = 1; //Why does this compile, shouldn't the Widget& be const?
}
Run Code Online (Sandbox Code Playgroud)
基本上,我有一个名为test的类.它在内部使用了四个小部件,我需要它来返回这些小部件,但如果测试被声明为const,我希望小部件也返回const.
有人可以向我解释为什么main()中的代码编译?
非常感谢你.
您需要创建一个专门用于保存const Widget和对象的新类型.即:
struct ConstWidgetHolder
{
ConstWidgetHolder(const Widget &a, const Widget &b, const Widget &c, const Widget &d): A(a), B(b), C(c), D(d){}
const Widget& A;
const Widget& B;
const Widget& C;
const Widget& D;
};
class Test
{
public:
ConstWidgetHolder AccessWidgets() const
{
return ConstWidgetHolder(A, B, C, D);
}
您现在将收到以下错误(在gcc 4.3中):
widget.cc: In function 'int main()': widget.cc:51: error: assignment of data-member 'Widget::x' in read-only structure
类似的习惯用法在标准库中使用迭代器,即:
class vector {
iterator begin();
const_iterator begin() const;
之所以能够编译,是因为虽然 WidgetHolder 是一个 const 对象,但这种 const 性不会自动应用于指向 WidgetHolder(由其引用)的对象。从机器级别考虑 - 如果 WidgetHolder 对象本身保存在只读内存中,您仍然可以写入 WidgetHolder 指向的内容。
问题似乎出在这一行:
WidgetHolder(Widget a, Widget b, Widget c, Widget d): A(a), B(b), C(c), D(d){}
Run Code Online (Sandbox Code Playgroud)
正如 Frank 提到的,构造函数返回后,WidgetHolder 类中的引用将保留无效引用。因此,您应该将其更改为:
WidgetHolder(Widget &a, Widget &b, Widget &c, Widget &d): A(a), B(b), C(c), D(d){}
Run Code Online (Sandbox Code Playgroud)
完成此操作后,它将无法编译,我将其作为练习留给读者来解决解决方案的其余部分。
| 归档时间: |
|
| 查看次数: |
1039 次 |
| 最近记录: |