class Foo
{
int Bar;
public:
int& GetBar() const
{
return Bar;
}
}
GetBar
是const
方法可以吗?它实际上并没有改变任何东西,但它为“外部世界”提供了一种改变它的方法。
答案 0 :(得分:19)
您的代码中有拼写错误,这可能是您的意思:
class Foo
{
int Bar;
public:
int& GetBar() const
{
return Bar; // Removed the ampersand, because a reference is returned, not an address
}
}
不,这不合法。使用const
标记方法时,不仅您承诺不会触及对象的任何内部状态,还承诺不会返回任何可用于更改对象状态的内容。可以使用非const引用来修改GetBar()
范围之外的Bar的值,因此您暗示您无法兑现承诺。
您必须将方法更改为非const,返回const引用,或通过将其标记为Bar
使mutable
免除承诺。例如:mutable int Bar;
mutable
关键字告诉编译器对象的逻辑const不依赖于Bar
的状态。然后你可以用它做任何你想做的事。
答案 1 :(得分:4)
不,因为你不能做以下任务:
const int x; int &y = x;
你可以做的是const int x; const int &y = x;
当然,重载方法并创建const和非const变体都没有问题。
答案 2 :(得分:3)
您可能想要返回Bar
,而不是&Bar
。无论如何,我在Comeau中删除了这段代码:
class Foo
{
int Bar;
public:
int& GetBar() const
{
return &Bar;
}
};
int main(int argc, char** argv)
{
Foo x;
int y = x.GetBar();
y = 5;
return 0;
}
得到了错误:
line 9: error: qualifiers dropped in binding reference of type
"int &" to initializer of type "const int"
return Bar;
^
答案 3 :(得分:1)
首先,要返回引用,您不需要在引用的对象上使用&符运算符;如果你想要一个指针,它是必需的。所以,我假设你想写return Bar;
。
然后,不,你不能这样做;在const
方法中,您有const
this
指针(在您的情况下,它将是const Foo *
),这意味着您可以访问其字段 1 将是const
引用,因为您通过“const
路径”访问它们。
因此,如果您尝试执行在该代码中执行的操作,则会出现编译错误,因为您尝试使用{{初始化int &
(方法的返回值) 1}}(你从const int &
获得的参考),显然是被禁止的。
Bar
这就是我刚才所说的。 testconstref.cpp: In member function ‘int& Foo::GetBar() const’:
testconstref.cpp:9: error: invalid initialization of non-const reference of type ‘int&’ from a temporary of type ‘const int*’
相反,如果您从:)
方法返回对{class}字段的const
引用,那么您将没有任何问题。
const
的字段,它告诉编译器即使从mutable
方法也可以修改这些字段;引入此异常是为了允许const
方法在不改变其“逻辑”状态的情况下改变对象的“真实”状态;这对于实现延迟评估,引用计数,......非常有用。答案 4 :(得分:1)
当您使用const方法时,您的类的成员被视为const。因此,尽管Bar
在您的班级中是int
而不是const int
,但在GetBar() const
的上下文中,它是“const int”。因此,将其作为非const引用或指针返回就像执行:
const int y = 57;
int& z = y;
这打破了const-correctness,即使第二行实际上没有改变y中的任何东西。
顺便提一下,如果你的类有指针成员,唯一的const就是指针本身,而不是指向它们的指针。 (通常称为“浅”常量)
因此这是合法的:
class A
{
Foo * foo;
public:
Foo * getFoo() const // legal. does not have to return const Foo *
{
return foo;
}
};
请注意,在原始代码中,如果它是Bar
,则允许您通过非const引用返回mutable
,因为这些成员不受成员函数的常量约束。
答案 5 :(得分:0)
const
修饰符不允许在其作用域中更改对象的状态。编译器只检查此函数是否在其范围内修改对象的状态。再举一个例子 -
class foo
{
int num ;
public :
foo( int anum )
{
anum = 10;
}
int getNum()
{
return num;
}
};
foo obj;
int& myNum = obj.getNum() ; // myNum is just an alias to the private class variable num
myNum = 40; // Actually changes the content of the private variable.
因此,编译器只检查访问说明符(即,此范围内是否可访问此变量),如果返回到其他变量,则不检查私有/公共/受保护变量的内存位置。