为什么c ++允许从外部类更改私有成员(是否为const)。 类之外的任何人都不能更改const成员。这似乎破坏了c ++封装。
#include <iostream>
#include <cstdlib>
#include <string>
class A
{
const std::string s;
public:
A():s{"abcd"}{};
const std::string& f()
{
return s;
}
};
int main()
{
A a;
std::string &s = const_cast<std::string&>(a.f());
s="efgh";
std::cout<<s<<std::endl;
std::cout<<a.f()<<std::endl;
return 0;
}
使用wandbox在线编译器上的c ++ 11进行编译。
g++ prog.cc -Wall -Wextra -I/opt/wandbox/boost-1.69.0/gcc-head/include -std=c++11
输出为:
efgh
efgh
我预期以下方面的编译错误: std :: string&s = const_cast(a.f());
如果没有方法可以不允许我从外部更改私有类成员(const或非const)。
答案 0 :(得分:4)
那是未定义的行为。
它允许您执行操作的事实并不意味着正确,通过非const修改const
对象是未定义的行为,任何事情都可能发生,包括工作的外观。
如果没有方法可以不允许我从外部更改私有类成员(const或非const)。
数据成员的可访问性在某种程度上与成员函数的可访问性及其作用无关,您可以拥有私有成员和公共函数来更改或赋予它们某些访问权限,而不会违反成员的固有属性。在您的示例中,foo
返回了对const std::string
的引用,该引用清楚地表达了意图(这是一个const对象),但是在外面,您违反了该意图。
答案 1 :(得分:1)
不是。
当您用const
剥去const_cast
时,实际上是关闭了您要保护的内容。那是你的责任。在一般情况下,C ++必须允许它允许“ hacks”。按照其理念,它不会做出任何努力阻止您违反合同。但是,最终您确实违约了,所以这是你的错!
因此,您的程序具有未定义的行为;即代码已损坏。
绕过private
很好,因为您是通过成员函数直接公开成员的。 (访问说明符保护的是名称,而不是对象,并且您的main
不使用私有名称。)同样,这是您的选择。 您破坏了类的封装。