如果对象声明为const,我想打破编译。
以下不起作用:
#include <type_traits>
struct A {
A() : v(0)
{
static_assert( ! std::is_const<decltype(*this)>::value, "declared as const" );
}
int& AccessValue() const
{
return const_cast< int& >( v );
}
int v;
};
int main()
{
A a1; // ok, this compiles
const A a2; // no, this break the compilation
a1.AccessValue() = 5; // ok
a2.AccessValue() = 6; // OPS
}
那么,如果这种类型的对象被声明为const,有没有办法打破编译?
答案 0 :(得分:3)
你走错了路。
this
的类型完全由您使用它的方法的签名决定。也就是说,this
始终为cv T* const
类型,其中cv
对应于方法的CV限定符。
因此,在构造函数中,this
只是T* const
。
const_cast
是代码气味,通常仅在处理const
时使用 - 破坏旧版库...或(有时)以避免违反DRY。在新代码中,您不必使用它。
您可以选择:
AccessValue
非const,因为它不是i
声明为mutable
。我建议选择以前的解决方案。放弃private
属性的句柄已经很糟糕(打破封装),也不需要违反const
正确性。
答案 1 :(得分:1)
对于您的具体示例,将i
变为可变将实现您的目标:
int& AccessValue() const
{
return v;
}
mutable int v;
这来自§7.1.6.1/ 4 [dcl.type.cv]:
除了可以修改任何声明为mutable(7.1.1)的类成员之外,任何在其生命周期内修改const对象的尝试(3.8)都会导致未定义的行为。
请注意,您无法使用const对象上的指针成员修改v
- n3290草稿[§5.5/ 5] [expr.mptr.oper]:
[注意:不可能使用指向成员的指针来引用可变成员来修改const类对象。例如,
struct S {
S() : i(0) { }
mutable int i;
};
void f()
{
const S cs;
int S::* pm = &S::i; // pm refers to mutable member S::i
cs.*pm = 88; // ill-formed: cs is a const object
}
- 结束说明]
答案 2 :(得分:0)
你可以有多个变量引用同一个对象,一些是可变的,一些是const。 例如:
A a1;
const A &a2 = a1;
A * const pa = &a1;
f(a1);
....
void f(const A &a);
在您的情况下是否允许这些? 从mutable到const的转换是隐含的,反之亦然。 也许如果你举一个例子会有所帮助。
编辑:(响应修改后的代码) 使用const对象,您只能调用const成员函数。 为什么没有:
int& AccessValue()
{
return v;
}
如果你在非const对象上调用AccessValue,那么抱怨的编译器。