能够更改私有常量类成员

Able to change private const class member

本文关键字:常量 成员      更新时间:2023-10-16

为什么 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不使用私有名称。同样,这是你的选择。破坏了类的封装。