繁体   English   中英

虚拟 function 调用非虚拟 function 反之亦然

[英]Virtual function calling a non-virtual function and vice versa

我有一个class A作为 class 的基础class B

我在我的虚拟function, xyz()中调用了非虚拟function, abc() ,如下所述。

由于运行时多态性, B:xyz被调用——我理解这一点。

但是,我不明白,为什么后面跟着B:abc而不是A:abc ,因为abc是非虚拟 function。

请注意:我遇到了以下问题: Virtual function calling a non-virtual function 它提到在虚拟 function 中调用abc()等效于this->abc() ,因此是 output。 但是,我不确定我是否理解这部分。

因为,当我做相反的事情(即非虚拟 function 调用虚拟函数)时,会显示正确的运行时多态性。 那么 this 指针会发生什么?

//Virtual function calling non-virtual 
class A
{
  public:
  void abc()
  {
    cout<<"A:abc"<<endl;
  }

  virtual void xyz()
  {
    cout<<"A:xyz"<<endl;
    abc();
  }
};


class B: public A
{
  public:
  void abc()
  {
    cout<<"B:abc"<<endl;
  }

  void xyz()
  {
    cout<<"B:xyz"<<endl;
    abc();
  }
};

int main() {

  A *obj3 = new B;
  obj3->xyz();\
  return 0;
}
Output
B:xyz
B:abc
//Non-virtual calling virtual function
#include <iostream>
using namespace std;

class A
{
  public:

  void abc()
  {
    cout<<"A:abc"<<endl;
    xyz();
  }

  virtual void xyz()
  {
    cout<<"A:xyz"<<endl;
  }
};

class B: public A
{
  public:

  void abc()
  {
    cout<<"B:abc"<<endl;
    xyz();
  }

  void xyz()
  {
    cout<<"B:xyz"<<endl;
  }
};

int main() {

  A *obj3 = new B;
  obj3->abc(); 
  return 0;
}
Output
A:abc
B:xyz

Calls to your non-virtual abc function are resolved, effectively, at compile time: so, when that is called from within another member function of class B , the class B version of the function is called, and is passed a pointer ( this )到调用它的 object; 同样,如果从class class A function 中调用,则将使用class A定义。 也就是说,对于编译器,非虚拟函数与 class 相关联,而不是与 class 的任何特定实例相关联。

但是,编译器对虚拟xyz function 的处理方式不同; 在这种情况下,对 function 的引用或指针被添加到 class 定义中(这通常被添加到所谓的vtable中,尽管细节是特定于实现的); 创建类的任何对象时,它们包括该 function 指针和/或 vtable 的副本。 当编译器看到调用这样一个虚拟 function 的代码时,它会通过适当的 function 指针将其转换为调用; so, the function 'travels with' the actual object: whether the function is called from the derived class or base class (in your code) is irrelevant – the function called is the one belonging to the object (instance) from which it is invoked .

总而言之:对非虚函数的调用在编译时被解析,而对虚函数的调用(在概念上)在运行时被解析。

要查看此“vtable”的实际创建,请尝试编译并运行以下代码:

#include <iostream>

class A {
public:
    int i;
    ~A() = default;
    void foo() { std::cout << i << std::endl; }
};

class B {
public:
    int i;
    virtual ~B() = default;
    virtual void foo() { std::cout << i << std::endl; }
};

int main()
{
    std::cout << sizeof(A) << std::endl;
    std::cout << sizeof(B) << std::endl;
    return 0;
}

这两个类之间的唯一区别是一个具有虚函数而另一个没有——但这会导致 class 对象的大小存在显着差异:vtable 的大小(可能带有一些“填充”以实现最佳对齐数据),(在我的 64 位 Windows 上,使用 MSVC,我得到的大小为 4 和 16。但实际值会因编译器和平台而异。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM