在下面的示例中,const
对象可以通过const
方法修改自身,因为在该方法中,它通过non-const
指针访问自身。 (same program on ideone)
#include <iostream>
struct Object;
Object * g_pObject;
struct Object
{
Object():m_a(0){}
void ModifySelfViaConstMethod() const
{
g_pObject->m_a = 37;
}
int m_a;
};
int main()
{
Object o;
g_pObject = &o;
const Object & co = o;
std::cout << co.m_a << "\n";
co.ModifySelfViaConstMethod();
std::cout << co.m_a << "\n";
return 0;
}
我对阅读c ++标准不太满意,所以我在这里问:
标准对此有何看法?
a)const
方法不保证您在执行此类操作时保持对象不会被修改
b)是否定义明确,必须编译
c)其他?
答案 0 :(得分:3)
当您声明const
函数时,它是“为了您自己的利益”。
换句话说,你声明它为const
,因为根据你的初始设计,它不应该改变在运行时调用它的任何对象。
如果在执行此函数的某个稍后阶段你最终更改了对象,编译器将“对你大吼大叫”,告诉你这是错误的。
当然,只有在this
上应用时,编译器才能识别此类尝试。
在给定的示例中,编译器无法识别问题,因为它需要在this
和g_pObject
之间进行比较,并且此类比较只能在运行时进行。
答案 1 :(得分:3)
当方法声明为const
时,编译器会确保this
指针指向的实例不会被修改。如果您尝试修改this
实例,则编译器将失败。但是,编译器无法知道g_pObject
和this
实际上指向同一个实例。这需要进行运行时比较,并且没有编译器会浪费时间执行const
方法内部使用的每个指针的运行时比较,因为它们可能匹配的可能性很小this
指针。因此,如果您要通过外部指针修改Object
,则必须进行自己的检查,例如:
void ModifySelfViaConstMethod() const
{
if (g_pObject != this)
g_pObject->m_a = 37;
}
答案 2 :(得分:1)
C ++中的稳定性是一种安全工具,而不是安全性。
遵循constancy的代码很可能会按预期工作,并且编译器会提醒所有无意中强制转换constancy的尝试。
如果“我知道自己在做什么”,可以找到各种各样的工具,从const_cast
运算符和mutable
关键字到平庸的C样式转换。
答案 3 :(得分:1)
标准对此有何看法?
它表示(释义)this
具有类型const Object *
,因此您无法通过this
直接修改成员或调用非const成员函数。它没有说明你可以对函数可能访问的任何全局变量做什么;它只控制对调用函数的对象的直接访问。
当您执行此类操作时,
const
方法无法保证您的对象不会被修改
不,不。它声明该函数不会修改对象的意图,并提供一些防止意外破坏该意图的保护。它不会阻止一个适当的疯狂程序员使用const_cast
,或(通过这里)通过全局变量进行不受控制的耦合来打破承诺。
是否已明确定义且必须编译
是。 o
本身并不是常数,所以没有什么可以阻止你采用非常量指针或引用它。成员函数上的const
仅限制通过this
访问对象,而不是通过其他指针访问任意对象。