带默认参数的虚函数,奇怪的输出

Virtual function with default argument, weird output

本文关键字:输出 默认 参数 函数      更新时间:2023-10-16

这段代码的输出是15,我真的不知道为什么。我认为它在foo函数中使用了x=5,但我不知道为什么。有人能帮我吗?

#include <iostream>
#include <string>
using namespace std;

struct A
{
    virtual int foo(int x = 5)
    {
        return x*2;
    }
};
struct B : public A
{
    int foo(int x = 10)
    {
        return x*3;
    }
};

int main(int argc, char** argv)
{
  A* a = new B;
  cout << a->foo();
  return 0;
}

我认为它在foo功能中使用x=5,但我不知道为什么。

是的,这里使用了基类A声明的默认参数(即5),因为您在静态类型A*的对象上调用foo()。默认实参是基于静态类型而不是动态类型来决定的。

标准对此有明确的解释,$8.3.6/10默认参数[dcl.fct.default]:

(强调我的)

虚函数调用([class.virtual])使用默认实参在由静态确定的虚函数声明中表示对象的指针或引用的类型。一个覆盖派生类中的函数不会从中获取默认参数它覆盖的函数。(例子:
struct A {
  virtual void f(int a = 7);
};
struct B : public A {
  void f(int a);
};
void m() {
  B* pb = new B;
  A* pa = pb;
  pa->f();          // OK, calls pa->B::f(7)
  pb->f();          // error: wrong number of arguments for B::f()
}

- end示例]

这个调用有两个部分:

  • 决定传递什么值给x -这是A::foo的默认参数,即5,因为这是a静态类型,即编译时已知的类型。如果你仔细想想,这是编译器唯一的选择,因为它不能假设分配给a的类型。
  • 决定哪个类接收调用 -这是B::foo,因为a所指向的对象的动态类型是struct B

因此你得到3*5作为你的输出