朋友调用虚拟私有方法 - 会发生什么

时间:2013-11-20 01:38:41

标签: c++ inheritance methods virtual friend

我有一种情况,我希望朋友类调用私有方法,然后我想让这个方法虚拟,所以派生一个类的方法将被调用 - 然后我当然意识到友谊不是继承的。所以我们有一种情况,其中虚方法意味着应该调用派生类的方法,但是这个方法是私有的,因此无法调用。哪个优先?

我在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时,这种行为会改变吗?

干杯

菲尔

2 个答案:

答案 0 :(得分:6)

§11.5/ 1-2([class.access.virt]):

  
      
  1. 虚函数的访问规则(第11条)由其声明决定,不受后来覆盖它的函数规则的影响。

  2.   
  3. 使用用于表示调用成员函数的对象的表达式类型在调用点检查访问...

  4.   

所以你升级很好。 (实际标准中有一个例子,但我把它留在了引用之外。)

实际上,这里发生的是Base虚函数执行其覆盖的发送。因此,即使您无法静态调用Derived覆盖(Derived::member),如果您有权访问Base::member,仍然可以Base::member为您调用它。

答案 1 :(得分:1)

通过具有“静态”类型Base*的对象指针进行调用 - 这是对其执行访问检查的类型。这些访问检查在编译时进行。由于LonerBase的朋友,编译器可以允许调用base->test()

但是,base指针指向的对象的动态类型为Derived。在运行时,没有额外的访问检查 - 调用动态类型,通过正常的虚拟调用机制进行调度。