我有一种情况,我希望朋友类调用私有方法,然后我想让这个方法虚拟,所以派生一个类的方法将被调用 - 然后我当然意识到友谊不是继承的。所以我们有一种情况,其中虚方法意味着应该调用派生类的方法,但是这个方法是私有的,因此无法调用。哪个优先?
我在MSVC ++ 2008上测试了这个,如下所示
#include<iostream>
class Loner;
class Base
{
friend Loner;
private:
virtual void test(){std::cout << "Base" << std::endl;}
};
class Derived : public Base
{
private:
virtual void test(){std::cout << "Derived" << std::endl;}
};
class Loner
{
public:
void test(Base *base){base->test();}
};
int main()
{
Loner loner;
Derived derived;
loner.test(&derived);
}
输出结果为:
Derived
所以似乎虚拟功能“获胜”并让私人成员访问非朋友 - 几乎是朋友继承!
我的问题是,有人知道这是否是正确的行为?当我最终完成升级我的编译器版本或者如果我尝试使用GCC时,这种行为会改变吗?
干杯
菲尔
答案 0 :(得分:6)
§11.5/ 1-2([class.access.virt]):
虚函数的访问规则(第11条)由其声明决定,不受后来覆盖它的函数规则的影响。
- 醇>
使用用于表示调用成员函数的对象的表达式类型在调用点检查访问...
所以你升级很好。 (实际标准中有一个例子,但我把它留在了引用之外。)
实际上,这里发生的是Base
虚函数执行其覆盖的发送。因此,即使您无法静态调用Derived
覆盖(Derived::member
),如果您有权访问Base::member
,仍然可以Base::member
为您调用它。
答案 1 :(得分:1)
通过具有“静态”类型Base*
的对象指针进行调用 - 这是对其执行访问检查的类型。这些访问检查在编译时进行。由于Loner
是Base
的朋友,编译器可以允许调用base->test()
。
但是,base
指针指向的对象的动态类型为Derived
。在运行时,没有额外的访问检查 - 调用动态类型,通过正常的虚拟调用机制进行调度。