C++ 引用和好友类的意外行为

C++ 引用和好友类的意外行为,c++,C++,使用friend关键字和引用时出现意外行为。代码如下: #include <iostream> class Modifier; class A{ private: int _a; friend Modifier; }; class B : public A {}; class Modifier { public: void f(A& i) { i._a = 10; std::cout << i._a << std::

使用friend关键字和引用时出现意外行为。代码如下:

#include <iostream>

class Modifier;

class A{
 private:
     int _a;
     friend Modifier;
};
class B : public A {};

class Modifier
{
public:
    void f(A& i) { i._a = 10; std::cout << i._a << std::endl; }
};
int main()
{
    Modifier m;
    B b;
    m.f(b);
}
// Output
// 10
#包括
类修饰语;
甲级{
私人:
国际组织;
朋友修饰语;
};
B类:公共A{};
类修饰语
{
公众:
空位f(A&i){i.\u A=10;标准::cout
B应该不能修改变量a

\u a
和包含它的对象是非常量的,因此可以修改
\u a
。声明成员私有不会阻止修改变量。访问说明符只影响可访问变量名称的范围

B
不修改变量
\u a
。修改
\u a
变量(变量
B
a
基本子对象的成员)的是
修饰符::f
.
Modifier
是类
a
的朋友,因此
Modifier
的成员函数可以访问
a
的私有声明名称。具有访问权限意味着它可以使用名称
a:\u a

B应该不能修改变量a

\u a
和包含它的对象是非常量的,因此可以修改
\u a
。声明成员私有不会阻止修改变量。访问说明符只影响可访问变量名称的范围


B
不修改变量
\u a
。修改
\u a
变量(变量
B
a
基本子对象的成员)的是
修饰符::f
Modifier
是类
a
的朋友,因此
Modifier
的成员函数可以访问
a
的私有声明名称。具有访问权限意味着它可以使用名称
a::\u a
B
已经无法修改
\u a
,因为它在
B
中声明为私有。它处于启用状态可在
A
中轻松访问。如果需要从
B
中读取
\u A
,请使用受保护的getter:

class A {
    protected:
        auto get_a() const { return _a; }

    private:
        int _a;
        friend Modifier;
};

B
已经无法修改
\u a
,因为它在
B
中声明为私有。它只能在
a
中访问。如果需要从
B
读取
\u a
,请使用受保护的getter:

class A {
    protected:
        auto get_a() const { return _a; }

    private:
        int _a;
        friend Modifier;
};

friend类可以访问声明为friend的其他类的私有和受保护成员。因此,
\u A
可以通过类
Modifier
的任何方法进行修改。但是,
B
不能修改
\u A
,因为它在类
A
中定义为私有。例如,如果您想导入在类
B
中删除方法
f
,则会得到编译器错误,该错误表示
'int A::_A'是私有的

class B : public A {    
    void f(A& i) { i._a = 10; std::cout << i._a << std::endl; }
};
B类:公共A{

无效f(A&i){i._a=10;std::coutafriend类可以访问声明为friend的其他类的私有和受保护成员。因此,
\u a
可以通过类
修改器
的任何方法进行修改。但是,
B
不能修改
\u a
,因为它在类
a
中定义为私有例如,如果您在类
B
中实现方法
f
,那么您将得到编译器错误,该错误表示
'int A::_A'是私有的

class B : public A {    
    void f(A& i) { i._a = 10; std::cout << i._a << std::endl; }
};
B类:公共A{

无效f(A&i){i._a=10;std::cout但您没有将
B
对象传递给
Modifier::f
,而是传递对
a
对象的引用。函数
Modifier::f
B
一无所知。B不应该能够修改变量_a.-为什么?作为一种可能的解决方案,创建一个
f
重载,使其引用
B
,并将其标记为已删除。即
void f(B const&)=delete;
。访问控制仅使用被访问对象的静态类型(出现在引用参数声明中的类型)。我不使用对象的动态类型(最派生的类型)你认为
Modifier
不能访问
\u a
,因为
B
是从
a
私下继承来的吗?如果是这样,你应该在问题中包含它。我花了一段时间,我仍然不确定你为什么认为
\u a
不能访问,但你是不将
B
对象传递给
Modifier::f
,而是传递对
a
对象的引用。函数
Modifier::f
B
一无所知。B应该不能修改变量_a。-为什么?作为一种可能的解决方案,创建一个引用
B
f
重载>,并将其标记为已删除。例如,
void f(B const&)=delete;
。访问控制仅使用访问对象的静态类型(出现在引用参数声明中的类型)。我不使用对象的动态类型(最派生的类型)你认为
Modifier
不能访问
\u a
,因为
B
是从
a
私下继承的吗?如果是这样的话,你应该把它包括在问题中。我花了一段时间,我仍然不确定你为什么认为
\u a
不能访问我同意t是修饰符::f修改了a,但我们看a到i,它是B的一个实例。编译器是否允许函数绕过私有关键字?@BleakMidWinter
Modifier
是友元,因此它有访问权。友元声明“绕过私有关键字”如果你想这样说的话。
\u a
是否在
B
的基础内是无关紧要的。我同意修改a的是修饰符::f,但我们看看B的一个实例_a到I。编译器是否允许函数绕过私有关键字?@blakmidw