为什么这个const成员函数允许修改成员变量?
class String
{
private:
char* rep;
public:
String (const char*);
void toUpper() const;
};
String :: String (const char* s)
{
rep = new char [strlen(s)+1];
strcpy (rep, s);
}
void String :: toUpper () const
{
for (int i = 0; rep [i]; i++)
rep[i] = toupper(rep[i]);
}
int main ()
{
const String lower ("lower");
lower.toUpper();
cout << lower << endl;
return 0;
}
class String
{
private:
char* rep;
public:
String (const char*);
void toUpper() const;
};
String :: String (const char* s)
{
rep = new char [strlen(s)+1];
strcpy (rep, s);
}
void String :: toUpper () const
{
for (int i = 0; rep [i]; i++)
rep[i] = toupper(rep[i]);
}
int main ()
{
const String lower ("lower");
lower.toUpper();
cout << lower << endl;
return 0;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
const 成员函数,是不会改变其成员变量的成员函数。
成员函数上的 const 并不意味着 const char *。 这意味着您无法更改指针保存的地址中的数据。
您的示例不会改变成员变量本身。
成员函数上的 const 将确保您将所有成员变量视为 const。
这意味着如果您有:
那么您将有:
有 2 种类型的 const 指针。 const 成员函数使用我上面列出的函数。
获得您想要的错误的方法:
尝试将:更改
为:
并删除此行:
它将抛出您期望的错误(由于 const 关键字而无法修改成员)
因为只有 1 个const 数组的类型。 这意味着您无法修改其任何数据。
现在整个系统实际上已经被下面的例子破坏了:
所以这里要学习的教训是成员函数上的 const 关键字并不能确保你的对象根本不会改变。
它只确保每个成员变量将被视为 const。 对于指针来说,const char * 和 char * const 之间有很大的区别。
大多数时候,const 成员函数意味着该成员函数不会修改对象本身,但情况并非总是如此,如上面的示例所示。
A const member function, is a member function that does not mutate its member variables.
const on a member function does not imply const char *. Which would mean that you can't change the data in the address the pointer holds.
Your example does not mutate the member variables themselves.
A const on a member function, will ensure that you treat all of your member variables as const.
That means if you have:
Then you will have:
There are 2 types of const pointers. A const member function uses the one I've listed above.
A way to get the error you want:
Try changing:
to:
And remove this line:
It will throw the error you are expecting (can't modify members because of const keyword)
Because there is only 1 type of const array. And that means you cannot modify any of its data.
Now the whole system is actually broken with the following example:
So the lesson to learn here is that the const keyword on member functions does not ensure that your object will not change at all.
It only ensures that each member variable will be treated as const. And for pointers, there is a big diff between const char * and char * const.
Most of the time a const member function will mean that the member function will not modify the object itself, but this is not always the case, as the above example shows.
原因是您没有更改
rep
。 如果愿意,您会在代码中的某处找到rep = ...;
。 之间的区别这是和
。在您的情况下,如果您执行 const 成员函数,则完成第一个操作:指针是 const。 因此,您将无法重置指针。 但是您很可能能够更改指针所指向的内容。
现在,请记住
rep[i] = ...;
与*(rep + i) = ...;
相同。 因此,您更改的不是指针,而是指针指向的内容。 允许,因为指针不属于第二种情况类型。解决方案
物理常量
。 但是,const 成员函数意味着您的对象是逻辑const
。 如果对某些内容的更改将更改对象的逻辑常量,例如,如果它更改了对象所依赖的某些静态变量,则编译器无法知道您的类现在具有另一个逻辑值。 它也不知道逻辑值的变化取决于指针指向的内容:编译器不会尝试检查 const 成员函数中的逻辑常量,因为它无法知道这些成员变量的含义。 这个东西被称为常量正确性
。std::string
,正如某些人所建议的那样,或者是一个字符数组(请注意,数组将不允许您更改其内容,而不仅仅是指针),将是一个合适的选择。2.
The reason is that you don't change
rep
. If you would, you would findrep = ...;
somewhere in your code. This is the difference betweenand
In your case, the first one is done if you execute a const member-function: The pointer is const. So, you won't be able to reset the pointer. But you will very well be able to change what the pointer points to.
Now, remember
rep[i] = ...;
is the same as*(rep + i) = ...;
. Thus, what you change is not the pointer, but what the pointer points to. You are allowed, since the pointer is not of the second case type.Solution
physical constness
. However, a const member-function means your object islogical const
. If a change to some content will change the logical constness of your object, for example if it changes some static variable that your object depends upon, your compiler cannot know that your class now has another logical value. And neither it can know that the logical value changes dependent on what a pointer points to: The compiler doesn't try to check logical constness in a const member function, since it cannot know what those member variables mean. This stuff is termedconst-correctness
.std::string
, as proposed by some, or an array of characters (note that an array will disallow you changing its content, as opposed to just a pointer), would be an appropriate choice.2.
toUpper() 不会更改指针(属于该类)。 它仅更改rep指向的数据(不属于该类)。
然而,“const”是对类的用户的一种保证:如果一个方法被声明为 const,那么使用类的实例的人可以期望在调用该方法时它不会改变。 我的观点是,如果 toUpper() 改变了字符串的状态,不要将其声明为 const,无论 C++ 是否允许。
toUpper() does not change the pointer (which belongs to the class). It only changes the data which rep points to (that do not belong to the class).
However, 'const' is a sort of warranty for the users of your class: if a method is declared const, who uses an instance of your class can expect it won't change when calling the method. My point is, if toUpper() changes the state of a string, don't declare it const, whether C++ allows it or not.
const 限定符意味着它不会更改类的任何成员。
在这种情况下,rep 是该类的唯一成员,我没有看到任何修改此成员的尝试。 类外部指向或引用的任何内容都不被视为该类的一部分。
此问题的解决方案是将 char* 替换为 std::string。
那么你只能从 toUpper() 中调用 std::string 的 const 成员,
例如(使用 std::string)
The const qualifier means it will not change any members of the class.
In this case rep is the only member of the class and I see no attempt to modify this member. Anything pointed at or referenced outside the class is not considered as part of the class.
A solution to this problem would be to replace the char* with a std::string.
Then you would only be able to call const members of std::string from within toUpper()
For example (use std::string)
值
您无法更改声明为或 的
,不幸的是,声明您的成员 const 会变成rep
,这意味着您无法更改实际地址,但可以更改内容,但无法更改值。
为了使 const memebrs 保持缓冲区常量,您需要使代表和字符数组或字符串对象而不是字符指针。
You cannot change the value of something declared as
or
Unfortunately, declaring your member const turns into rep into
which means, you cannot change the acutal address, but you can change the contents, whereas you cannot change the value.
To make const memebrs respect keep your buffer const, you will need to make rep and array of characters or a string object rather than a character pointer.