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

时间:2015-03-27 04:13:57

标签: c++ override virtual-functions late-binding default-arguments

在阅读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 bar\n";
  } 
};
class B : public A  
   {
 public:
   virtual void foo(int x = 20)
   {
     cout << "derived x : " << x << "\n";
   }
  private:
   virtual void bar()
   {
     cout << "derived bar\n";
   }

   };
   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())怎么可能?

2 个答案:

答案 0 :(得分:1)

似乎在编译时解析了默认参数。请参阅herehere

  

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

答案 1 :(得分:1)

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

  

虚函数调用(10.3)使用的默认参数   声明由静态类型确定的虚函数   表示对象的指针或引用。最重要的功能   在派生类中,不从中获取默认参数   功能它覆盖。

在您的示例中,默认参数的评估是基于&#34; p&#34;的类型完成的。这是&#34; A&#34;。因此,默认参数的评估是从A的声明完成的,函数的调用是通过vptr表中的常规查找来完成的。