【问题标题】:friend calls virtual private method - what should happen朋友调用虚拟私有方法 - 应该发生什么
【发布时间】:2013-12-03 20:16:03
【问题描述】:

我有一种情况,我想让一个朋友类调用一个私有方法,然后我想让这个方法成为虚拟方法,所以派生类的方法会被调用——然后我当然意识到友谊不是继承的。所以我们有一种情况,虚拟方法意味着应该调用派生类的方法,但是这个方法是私有的,所以不能调用。哪个优先?

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

干杯

菲尔

【问题讨论】:

标签: c++ inheritance methods virtual friend


【解决方案1】:

调用是通过一个“静态”类型为Base* 的对象指针进行的——这是执行访问检查的类型。这些访问检查发生在编译时。由于LonerBase 的朋友,因此编译器可以允许调用base-&gt;test()

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

【讨论】:

    【解决方案2】:

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

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

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

    所以你很高兴升级。 (实际标准中有一个示例,但我在引用中省略了它。)

    实际上,这里发生的事情是Base 虚函数将发送到它的覆盖。因此,即使您不能静态调用 Derived 覆盖 (Derived::member),如果您有权访问 Base::member,您仍然可以让 Base::member 为您调用它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-09-07
      • 2011-02-04
      • 2010-09-27
      • 2018-01-05
      • 1970-01-01
      • 2012-08-21
      相关资源
      最近更新 更多