gpt4 book ai didi

c++ - 为什么派生类的 friend 不能使用 protected 成员?

转载 作者:行者123 更新时间:2023-12-01 13:06:46 25 4
gpt4 key购买 nike

C++ 标准声明于 [class.access/1] (强调我的):

A member of a class can be

  • private; that is, its name can be used only by members and friends of the class in which it is declared.
  • protected; that is, its name can be used only by members and friends of the class in which it is declared, by classes derived from that class, and by their friends (see [class.protected]).
  • public; that is, its name can be used anywhere without access restriction.


那么为什么编译器会在下面的 C++ 程序中引发这个错误呢?

#include <iostream>

class B {
protected:
static int const i = 1;
};

class D: public B {
public:
void f();
friend void g();
};

void D::f() {
B b;
std::cout << b.i; // OK
}

void g() {
B b;
std::cout << b.i; // error: 'i' is a protected member of 'B'
}

int main() {
D d;
d.f();
g();
return 0;
}

请注意 protected 数据成员 B::i被声明为静态不受 [class.access/class.protected-1] 中 protected 非静态成员所特有的进一步限制的约束。这也会在 b.i 上引发相同的错误在 D::f 中访问成员函数与 g 中的相同功能。

笔记。 — 我在 Clang 9.0.0 编译器上使用 C++ 17。

最佳答案

这似乎是一个规范问题。我引用的部分与另一部分不同步,另一部分指定了 Clang 遵循的新正确行为(但不是 GCC 或 MSVC 令人惊讶),[class.access/base-5] (强调我的):

A member m is accessible at the point R when named in class N if

  • m as a member of N is public, or
  • m as a member of N is private, and R occurs in a member or friend of class N, or
  • m as a member of N is protected, and R occurs in a member or friend of class N, or in a member of a class P derived from N, where m as a member of P is public, private, or protected, or

  • 存在 N 的基类 B 可在 R 处访问,并且当在类 B 中命名时,可在 R 处访问 m。

  • 这里没有提到派生类的 friend 。但它曾经是。由于缺陷报告 CWG 1873,它已在 C++17 中删除(强调我的):

    Protected member access from derived class friends

    Section: 14.2 [class.access.base] Status: CD4 Submitter:Richard Smith Date: 2014-02-18

    [Moved to DR at the May, 2015meeting.]

    According to 14.2 [class.access.base] paragraph 5,

    A member m is accessible at the point R when named in class N if

    • m as a member of N is protected, and R occurs in a member or friend ofclass N, or in a member or friend of a class P derived from N, where mas a member of P is public, private, or protected, or

    The granting of access via class P is troubling. At the least, thereshould be a restriction that P be visible at R. Alternatively, thisportion of the rule could be removed altogether; this provision doesnot appear to be widely used in existing code and such references canbe easily converted to use P instead of N for naming the member.

    Notes from the June, 2014 meeting:

    CWG noted that removing the friend provision would introduce anundesirable asymmetry between member functions of P and its friends.Instead, the intent is to require P to be a complete type at R.

    Notes from the November, 2014 meeting:

    Although the asymmetry is unfortunate, the difference between areference in a member function and a reference in a friend is that themember function concretely determines which P is in view, while thefriend could be befriended by a class that is a specialization of aclass template and thus would require instantiations that would nototherwise occur. CWG thus decided simply to eliminate the friend case.

    Proposed resolution, November, 2014:

    Change bullet 5.3 of 14.2 [class.access.base] as follows:

    A member m is accessible at the point R when named in class N if

    • m as a member of N is protected, and R occurs in a member or friend ofclass N, or in a member or friend of a class P derived from N, where mas a member of P is public, private, or protected, or
    • there exists…

    我已经在 GitHub 上提交了一个 pull request 来纠正这个不一致: https://github.com/cplusplus/draft/pull/3672

    关于c++ - 为什么派生类的 friend 不能使用 protected 成员?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60178872/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com