[英]How does friend class of the base class access members of that base class through objects of class derived from the base class?
这是我在文件source.cpp中的代码:
class B
{
friend class F;
protected:
int protectedIntB;
};
class D : public B {};
class F
{
public:
int f(D &d) {return ++d.protectedIntB;}
};
当我使用g++ -c -Wall -pedantic -std=c++11 source.cpp
和cl /c source.cpp
编译以上代码时,两个编译器均成功编译。 但是,当我使D使用protected
而不是public
从B继承时:
class D : protected B {};
这次,gcc成功编译,而cl给出错误,表明B::protectedIntB
在return ++d.protectedIntB;
不可访问return ++d.protectedIntB;
。
另一种情况是将public
替换为private
:
class D : private B {};
这次,两个编译器都产生错误。 顺便说一句,我正在使用mingw-w64构建的gcc版本5.3.0和VS2015的cl版本19.00.24210。
我的问题来了:
基类的好友类如何通过从基类派生的类的对象访问该基类的成员,以及为什么gcc和cl处理不同?
编辑:
感谢songyuanyao和Brian ,在protected
情况下,它似乎在gcc 5.3.0中存在错误。 只有public
情况才能成功编译,并且gcc 6.1.0也可以正常工作。
根据[class.access.base] / 5:
对成员的访问受该成员所在的类影响。 该命名类是在其中查找并找到成员名称的类。
根据[class.access.base] / 6:
如果使用包含隐式“
this->
”的类成员访问运算符来访问非静态数据成员或非静态成员函数,则如果左操作数(在指针中被视为指针)则引用格式不正确。 “.
”运算符大小写)不能隐式转换为指向右侧操作数命名类的指针。
因此,在特定情况下,要访问d.protectedIntB
,以下两个条件必须为真:
您必须作为B
的成员有权访问protectedIntB
,因为B
是在其中找到了protectedIntB
名称的类。 (注意:这可以通过使用using-声明在派生类中重新声明成员来更改;在这种情况下,派生类将是控制对象。)
您必须有权访问B
作为D
的基础, 即,能够将D*
转换为B*
。 如果B
是D
的公共基础,则很好。 如果B
是一个受保护的基础D
,访问检查适用,这F::f
失败,因为F
不是朋友D
,而不是派生类的D
。
如果使D
使用受保护的或私有的(而不是公共的)从B
继承,则编译将失败。
根据标准, $ 11.2 / 5基类和基类成员的可访问性[class.access.base] :
如果在类N中命名,则成员m在点R处可访问。
(5.4)存在一个N的基类B,它可以在R处访问,而在B类中命名时,m可以在R处访问。
class B; class A { private: int i; friend void f(B*); }; class B : public A { }; void f(B* p) { p->i = 1; // OK: B* can be implicitly converted to A*, // and f has access to i in A }
—结束示例]
对于您的第一种情况,可以通过F::f()
访问D
的基类B
,因为它是公共继承。 B::protectedIntB
是F::f()
类的朋友,因为它是B
类的朋友。
如果将其更改为受保护继承或私有继承,则D
的基类B
不能再次在F::f()
访问,则编译应会失败。 注意F::f()
不是派生类D
朋友。 这意味着如果您也使它成为D
类的朋友,则编译将成功。
顺便说一句:我在这里用gcc尝试了受保护的继承,但失败了。
如果代码在gcc 5.3.0上编译而不在cl上编译,则这两者之一没有严格执行C ++标准的可能性很高。 如果我不得不猜测一下,对于受保护的私有继承,您应该会遇到编译器错误。 有关不同种类的继承之间的区别,请参阅私有,公共和受保护继承之间的区别以获取更多详细信息。
为了使F类能够访问B类的私有成员,应该知道D类是从B类派生的,而B类只会发生在公共继承中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.