朋友调用虚拟私有方法-应该发生什么
friend calls virtual private method - what should happen
我有一种情况,我想让一个朋友类调用一个私有方法,然后我想让这个方法虚拟化,这样派生类的方法就会被调用——然后我当然意识到友谊不是继承的。因此,我们有一种情况,虚拟方法意味着应该调用派生类的方法,但这个方法是私有的,因此不能调用。哪个优先?
我在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,这种行为会改变吗?
干杯
Phil
§11.5/1-2([class.access.virt]):
虚拟函数的访问规则(第11条)由其声明决定,不受后来覆盖它的函数的规则的影响。
访问在调用点使用表达式的类型进行检查,该表达式用于表示调用成员函数的对象。。。
所以你很适合升级。(实际标准中有一个例子,但我把它排除在报价之外。)
实际上,这里发生的是Base
虚拟函数对其覆盖进行发送。因此,即使您不能静态调用Derived
覆盖(Derived::member
),如果您有权访问Base::member
,您仍然可以让Base::member
为您调用它。
调用是通过"static"类型为Base*
的对象指针进行的,这是执行访问检查的类型。这些访问检查发生在编译时。由于Loner
是Base
的朋友,因此编译器可以允许调用base->test()
。
然而,base
指针指向的对象的动态类型是Derived
。在运行时,没有额外的访问检查——调用是对动态类型进行的,动态类型是通过正常的虚拟调用机制进行调度的。
相关文章:
- 什么时候调用组成单元对象的析构函数
- 什么时候调用析构函数
- 有什么好的方法可以让系统调用代理允许在单元测试中进行模拟
- boost odeint什么时候真正调用观测者
- unique_ptr:在分配之前调用 reset 有什么效果
- 是什么让放置新调用对象的构造函数?
- 使用基类指针调用基类的值构造函数的语法是什么?
- C++:使用方法调用析构函数的顺序是什么?
- 这个C++编译器优化(在自身的实例上调用对象自己的构造函数)的名称是什么,它是如何工作的?
- C++有什么方法可以在既不调用函数模板也不提供其模板参数的情况下引用函数模板?
- 什么是仅调用一次并调用参数的控制台应用
- 使用动态链接加载程序 <dlfcn.h> 而不是直接函数调用的目的是什么?
- 什么时候可以使用常量装饰调用我的重载函数?
- 如果结构中的字符串比使用的 p/调用签名长或短,会发生什么情况?
- 我正在尝试学习如何在 c++ 中传递指针,但出现错误:没有用于调用"test"的匹配函数。我做错了什么?
- 当我从 std::vector 中的新放置调用析构函数时会发生什么?
- "noexcept-expression 由于对......的调用而计算为'假'"是什么意思?
- 运算符++();调用和++(*this)有什么区别?
- C++ 此函数调用之前的(void)有什么作用?
- C++:将向量传递给函数,然后在main中调用函数.错过了什么