能够更改私有常量类成员
Able to change private const class member
为什么 c++ 允许从类外部更改私有成员(常量与否)。类外的任何人都不能更改 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
对象是未定义的行为,任何事情都可能发生,包括工作的外观。
数据成员的可访问性与成员函数如果没有方法,我不应该被允许以任何方式从外部更改私有类成员(常量或非常量)。
的可访问性及其作用无关,您可以让私有成员和公共函数在不违反成员固有属性的情况下更改或授予对它们的某些访问权限。在您的示例中,foo
向清楚地表达意图的const std::string
返回一个 ref(它是一个 const 对象),但在您外部违反了该意图。
它没有。
当你用const_cast
剥离const
时,你实际上关闭了你所要求的保护。这是你的责任。C++必须允许这样做才能在一般情况下允许"黑客攻击";根据其理念,它不会认真努力阻止您违反合同。但是,最终,你确实违反了合同,所以这是你的错!
因此,您的程序具有未定义的行为;即代码被破坏。
绕过private
是完全可以的,因为您通过成员函数直接公开成员。(访问说明符保护名称,而不是对象,并且您的main
不使用私有名称。同样,这是你的选择。你破坏了类的封装。
相关文章:
- 私有类型的静态常量成员
- constexpr构造函数需要常量成员函数时出现问题
- Clang 格式 10.0 与 5.0 常量成员函数的格式不同
- 为什么"具有常量成员的结构"类型的指针不能指向"具有非常量成员的结构"?
- 常量成员函数中成员变量的类型
- 如何处理运算符=中的常量成员?
- 常量成员和没有setter的私有成员之间有什么区别
- C++:允许临时对象调用非常量成员函数的设计理念是什么?
- 移动具有常量成员的类的构造和分配
- ARM C++编译器不会编译具有可变常量成员的结构
- 强制在编译时计算类的类的常量成员
- 类中常量成员函数的 c++ 链接错误
- 为什么常量成员可以初始化两次?
- 专用常量成员函数的成员检测
- 与其他静态const成员初始化静态常量成员
- 具有静态和常量成员变量的对象
- 结构中的常量成员即使在初始化后也返回 0
- 在非常量成员函数中,为什么点这个非常量,而 decltype 指针这是常量
- 有没有一种通用方法来"unprotect"静态常量成员?
- 如何初始化共享复杂初始化代码的多个常量成员变量?