我正在研究C ++。以下是我的代码:
#include <iostream>
using namespace std;
class base
{
public:
virtual void display(int a = 4)
{
cout << "base :: "<< a*a << endl;
}
};
class derived : public base
{
public:
void display(int b = 5)
{
cout << " Derived :: " << b*b*b << endl;
}
};
int main()
{
base *bobj;
derived dobj;
bobj = &dobj;
bobj->display();
return 0;
}
输出结果为:
Derived :: 64
调用Base类的函数,但使用派生函数的参数的默认值。 为什么派生类方法display()采用基类方法参数值?
答案 0 :(得分:7)
因为你是通过指向base
的指针来调用它的。这就是它的工作原理。
在实际调用之前,在参数堆栈(或寄存器内)上推送参数。因为您有一个指向base
且没有参数的指针,所以默认4
将传递给该函数。然后调用正确的函数(derived::display
),但使用base
的默认参数。当然,这是一个实现细节,但行为是标准的。
虚函数调用(10.3)使用静态确定的虚函数声明中的默认参数 表示对象的指针或引用的类型。派生类中的重写函数不会获取默认值 来自它覆盖的函数的参数。
我会强调引用,但整件事情都是不言自明的。
dobj.display();
会打印125
(5 ^ 3)。
答案 1 :(得分:2)
调用者插入默认参数。您的代码等同于
class base {
public:
virtual void display(int a) { cout << "base :: "<< a*a << endl; }
inline void display(void) { display(4); }
};
等
通过base
指针调用时,会插入基类的默认值。
答案 2 :(得分:2)
标准说明了一切:
(§8.3.6/ 10)虚函数调用(10.3)使用由表示对象的指针或引用的静态类型确定的虚函数声明中的默认参数。派生类中的重写函数不会从它覆盖的函数中获取默认参数。 [例如:
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 example ]
答案 3 :(得分:0)
当你使用->
,即使用指针调用一个函数时,它使用被指向的对象做出决定,在这种情况下是Derived
类的对象。
正如规范所说......
虚函数调用使用由表示对象的指针或引用的静态类型确定的虚函数声明中的默认参数。派生类中的重写函数不会从它覆盖的函数中获取默认参数。
答案 4 :(得分:0)
让自己成为一个不那么做作的测试设置,并且很明显:
#include "base.hpp"
int compute(base * p)
{
return p->display();
}
现在有两件事情是显而易见的:
默认参数只能来自base
中指定的默认参数。
实际调度是动态的,因为display
是虚拟成员函数。