【问题标题】:Call private virtual functions from Base class object从基类对象调用私有虚函数
【发布时间】:2015-11-04 09:40:58
【问题描述】:

我了解到最好将虚函数保持私有,但是在我下面发布的代码中,除非友谊可以继承,否则函数call_inside()应该无法调用D1类中定义的虚函数。所以我想知道它是如何工作的。

感谢您的回复。

#include<iostream>
struct B
{
friend void call_inside();
private:
  virtual void fun()  {std::cout<<"virtual_B"<<std::endl;}
};
struct D1:public B
{
private:
  void fun()override  {std::cout<<"virtual_D1"<<std::endl;}
};
void call_inside()
{
  B trial; D1 trial1;
  B *p=&trial, *p1=&trial1;
  p->fun();
  p1->fun();
}
int main()
{
  call_inside();
  return 0;
}

【问题讨论】:

  • 我自己有一个解释:我在它的友元函数中调用了 B 的私有成员,因此它在编译时是完全合法的。调用哪个版本的虚函数是在运行时确定的,此时 D1 的私有说明符无关紧要。不知道有没有道理
  • 如果你想增加令人头疼的功能,请删除friend 声明,仅在B 中公开fun(),然后尝试p1-&gt;fun()trial1.fun() ;)

标签: c++ virtual private


【解决方案1】:

call_inside 函数是B 的朋友。在call_inside 中,您调用fun 两次,都是通过指向B 实例的指针。 B 指针之一实际上指向D 这一事实并不重要,因为用于调用函数的指针的类型是B。如果您改为在call_inside 中调用trial1.fun(),您将收到预期的编译错误,因为funD 上是private,并且您尝试通过D 实例调用它。

【讨论】:

  • 但实际上 D1 的私有虚函数将在运行时被非友元函数调用。我们可以说私有说明符在运行时无关紧要吗?
  • 运行时肯定不会为了验证函数访问而进行类型检查,如果这就是你的意思的话。在编译时检查访问说明符。该函数在B 的实例上调用,它是属于B 的函数,并且在覆盖它时D 已同意成为其调用协议的一部分。在这种情况下,公共继承意味着D is-a B
  • 非常感谢。但是尽管D 是从B 继承的公共成员,B 的私有成员仍然应该对D 隐藏。对吗?
  • 是的,但是关于funD 覆盖了它的基础B 的虚函数。此外,我无法访问任何最新的 C++ 标准,但 1998 年标准对访问说明符和虚函数有这样的说法:“在调用点使用用于表示对象的表达式类型检查访问权限成员函数被调用(B* 在上面的例子中)。成员函数在定义它的类中的访问(D 在上面的例子中)通常是未知的。我猜想最近的标准仍然相当接近这些规则。
猜你喜欢
  • 2010-09-28
  • 2021-09-26
  • 2013-06-29
  • 2013-03-25
  • 2016-10-08
  • 2018-05-11
  • 1970-01-01
  • 1970-01-01
  • 2016-01-22
相关资源
最近更新 更多