如果将访问控制应用于朋友该怎么办?

时间:2019-03-23 12:56:07

标签: c++ language-lawyer

我正在阅读C ++ 11 Standard(N3092)。

11-4成员访问控制

  

访问控制统一应用于所有名称,无论名称是从声明还是表达式中引用。 [注意:访问控制适用于由朋友声明((11.4)和using-声明(7.3.3)提名的名称。 —尾注]

11.4-9朋友

  

由朋友声明指定的名称应在包含该朋友声明的类的范围内可访问。 朋友声明的含义与朋友声明出现在类成员规范的私有,受保护或公共(9.2)部分中一样。

由于我的英语水平差,这两个摘录似乎不一致。如第一节摘录所述,如果将访问控制应用于friend,该怎么办?谁能给我一个具体的示例代码?


第一节摘录还提到了using声明。可以通过下面的代码确认。因此,您可以说“访问控制肯定适用于使用声明”。但是我不知道如何编写代码来查看访问控制的friend函数的行为。

#include <iostream>
using std::cout;

class B {
    public:
        void f() { cout << "B::f()\n"; }
        void f(int) { cout << "B::f(int)\n"; }
};

class D : public B {
    public:
        using B::f; //`using` declaration in `public` context
        void f() { cout << "D::f()\n"; }
};

class D2 : public B {
    using B::f; //`using` declaration in `private` context
    public:
        void f() { cout << "D2::f()\n"; }
};

int main() {

    D d;
    d.f(); //=> "D::f()"
    d.f(0); //=> "B::f(int)"

    D2 d2;
    d2.f(); //=> "D2::f()"
    d2.f(0); //=> "error: ‘void B::f(int)’ is inaccessible within this context"

}

如上面的代码,如果我写

public:
    friend void some_func() { }

,访问控制是否应用于名称some_func?怎么样?

1 个答案:

答案 0 :(得分:3)

  

这两个摘录似乎不一致

它们是一致的,但不一定如此。 [note: ]块中的所有内容均为非标准文本。此处仅出于人类目的进行概述或提供澄清的示例,但并未用于定义语言的实际行为。因此,唯一重要的摘录是第二篇。

第一节摘录中的黑体字是关于朋友声明的内容。如果您有AB这两个类,并且想让B的特定成员成为A的朋友,则粗体字表示的是A必须已经可以访问您指定的特定成员。也就是说,这是非法的:

class B
{
private:
  void SomeMember();
};

class A
{
private:
  friend void B::SomeMember(); //`SomeMember` is not accessible to `A`, so ill-formed.
};

B必须使自己成为A的朋友,以便A可以命名其私有成员。

第二节摘录中的粗体文本仅表示friend声明在类中发生的位置无关紧要。 friend声明是公共的,私有的还是其他无关紧要。也就是说,以下所有内容都表示同一件事:

class B;

class A1
{
public:
  friend class B;
};

class A2
{
protected:
  friend class B;
};

class A3
{
private:
  friend class B;
};

因此,两个粗体摘录彼此无关。

现在,第二节中未加注释的部分实际上用规范性语言说出了第一节摘录中的含义。即,friend声明中指定的名称必须可访问。

  

如果我写<...>访问控制是否应用于名称some_func?怎么样?

很好。 friend 定义始终定义非成员函数。因此,它们不在类的范围内,因此实际上是public。因此可以访问。