【问题标题】:concept involved here in function calling and argument passing这里涉及函数调用和参数传递的概念
【发布时间】:2015-03-27 04:13:57
【问题描述】:

在阅读 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())?

【问题讨论】:

  • 你看到this了吗?

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


【解决方案1】:

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

虚函数调用 (10.3) 使用默认参数 由静态类型决定的虚函数的声明 表示对象的指针或引用。一个覆盖函数 在派生类中不会从 它覆盖的函数。

在您的示例中,默认参数的评估是根据“p”类型(即“A”)完成的。因此,默认参数的评估是从 A 的 声明 完成的,而函数的调用是通过在 vptr 表中的通常查找来完成的。

【讨论】:

  • **默认参数的评估是基于“p”类型的“A”。 ** -- 是的,我能理解这个概念,非常感谢。
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-03-11
    • 1970-01-01
    • 2011-07-02
    • 2012-11-18
    • 2020-01-12
    • 1970-01-01
    • 2022-10-05
    • 1970-01-01
    相关资源
    最近更新 更多