Ant*_*ant 4 c++ inheritance friend
来自C++ Primer第5版(D继承自B)
如果D使用public或protected从B继承,则从D派生的类的成员函数和朋友可以使用derived-tobase转换.如果D从B私下继承,则此类代码可能不会使用转换.
这有什么理由,还是我打算以面值来表达它?似乎很明显为什么会这样,但它在一个例子中绊倒了我:
#include <iostream>
using namespace std;
class Base {
public:
int x = 2;
};
class Derived : protected Base { };
class DerivedAgain : public Derived {
friend void test();
};
void test() {
??? a;
Base* p = &a;
cout << p->x;
}
int main(){
test();
}
Run Code Online (Sandbox Code Playgroud)
我想了解派生到基础转换中test()成员的可访问性x.考虑到三种潜在???的a功能类型的案例test().
???是Base.x是公共成员Base.在这种情况下没有问题.???是DerivedAgain.在这种情况下,Derived-to-Base转换是有意义的,因为test()可以friend访问所有成员DerivedAgain,包括间接从中继承的成员Base.因此使用指针访问没有问题x.???是Derived.它汇编很好.但为什么?我在这一点上很困惑.test()没有对Derived类成员的特殊访问权限,那么为什么要p->x工作并因此Derived-to-Base转换有效呢?这有效吗?事实上,如果我改变的操作test()来
void test() {
Derived a;
cout << a.x;
}
Run Code Online (Sandbox Code Playgroud)
它不会像我期望的那样编译 - 因为对象继承的x成员Derived是protected由用户创建的,因此不能被用户使用.
如果我更换的类型a与Base和DerivedAgain修改test()编译罚款,因为我希望它.
我很困惑为什么允许二级派生类的友元函数使用第一级直接到基本的转换,如果该友元函数没有对第一级派生类成员的特殊访问权限.
基本上,受保护的继承是很奇怪的.它编译的原因是,从N4527起的[class.access.base]:
基类
B的N是可以访问在[R ,若
-的发明公共成员B将是公共成员N,或者
- [R类的成员或朋友时N,和的发明公共成员B将是私人或受保护的成员N,或者
- R发生在P派生自的类的成员或朋友中N,并且发明的公共成员B将是私人或受保护的成员P,或者
- 存在一个类S,这B是一个S可在R和R访问的基类S是一个基类的N可从R访问.
这里的第三个要点是相关的.ř在朋友(发生test一类)P(DerivedAgain)衍生自N(Derived),和一个公共发明构件B(Base)将是一个受保护的构件P(DerivedAgain).
我以前认为接受这个代码是一个gcc错误(错误67493),但现在我认为不接受它是一个铿锵的错误 - 尽管TC另外指出,有一个相关的标准缺陷(CWG#1873).那里的措辞变化仅适用于成员访问,而这里与我们相关的是基本访问.但也许gcc只是实施标准规则(接受是正确的)而clang遵循这个缺陷报告的逻辑结论(目前活跃的CWG#472)并且不允许它.
同样,受保护的继承真的很奇怪.欢迎来到C++的精彩世界.