函数调用和参数传递中涉及的概念

concept involved here in function calling and argument passing

本文关键字:参数传递 函数调用      更新时间:2023-10-16

在阅读vptr和vtable概念时,我得到了一段精彩的代码,但我无法理解这里涉及的概念:

#include <iostream>
using namespace std;
class A
{
 public:
  virtual void foo(int x = 10)
  {
    cout << "base x : " << x << "n";
  }
  virtual void bar()
  {
    cout << "base barn";
  } 
};
class B : public A  
   {
 public:
   virtual void foo(int x = 20)
   {
     cout << "derived x : " << x << "n";
   }
  private:
   virtual void bar()
   {
     cout << "derived barn";
   }
   };
   class C : public B
   {
   };
   int main()
   {
     A x; x.foo(); // x.foo(10);
     B y; y.foo(); // x.foo(20);
     A *p(&y);
     p->foo(); 
   }

现在我得到的输出是:

base x : 10
derived x : 20
derived x : 10

即使在打印派生x(即B::foo())时,默认参数也是基函数(即A::foo)的参数,这怎么可能呢?

C++标准第8.3.6节第10点提到:

虚拟函数调用(10.3)使用由的静态类型确定的虚拟函数的声明表示对象的指针或引用。覆盖函数在派生类中,不从它覆盖的函数。

在您的示例中,默认参数的评估是基于"p"类型(即"A")进行的。因此,默认参数的计算是从A的声明中完成的,函数的调用是通过vptr表中的常规查找进行的。

默认参数似乎是在编译时解析的。看看这里和这里。

使用的默认值将是在静态(编译时)类型中定义的值。因此,如果要更改重写中的默认参数,但通过基类指针或引用调用函数,则将使用基类中的默认值。