Are*_*yst 7 c++ virtual derived default-parameters
有人可以解释为什么下面的代码的结果将是"B类:: 1"?
为什么派生类的虚方法使用基类的默认参数而不是自己的默认参数?对我来说这很奇怪.提前致谢!
码:
#include <iostream>
using namespace std;
class A
{
public:
virtual void func(int a = 1)
{
cout << "class A::" << a;
}
};
class B : public A
{
public:
virtual void func(int a = 2)
{
cout << "class B::" << a;
}
};
int main()
{
A * a = new B;
a->func();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
因为默认参数是根据静态类型this(即变量本身的类型,如A&in A& a;)解析的.
稍微修改您的示例:
#include <iostream>
class A
{
public:
virtual void func(int a = 1)
{
std::cout << "class A::" << a << "\n";
}
};
class B : public A
{
public:
virtual void func(int a = 2)
{
std::cout << "class B::" << a << "\n";
}
};
void func(A& a) { a.func(); }
int main()
{
B b;
func(b);
b.func();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我们观察到以下输出:
class B::1
class B::2
Run Code Online (Sandbox Code Playgroud)
在ideone行动.
由于这个原因,不建议虚函数更改默认值.不幸的是,我不知道任何编译器警告这个结构.
技术说明是有两种处理默认参数的方法:
void A::func() { func(1); }a.func()=>a.func(/*magic*/1)如果它是前者(假设A::func声明virtual也是如此),那么它会像你期望的那样工作.然而,后一种形式是选举产生的,要么是因为virtual当时没有预见到问题,要么因为它们被认为是无关紧要的(如果有的话......).
因为C++中的多态性在运行时生效,而默认参数的替换在编译时生效.在编译时,编译器不知道(并且不应该知道)指针所a指向的对象的动态类型.因此,它采用它所知道的唯一类型的默认参数a,在您的示例中是A *.
(顺便提一下,这也是接口/头部而不是实现/定义中给出默认参数的原因.编译器从不在实现的机器代码中插入默认参数,而只在调用者的机器代码中插入.技术上,默认参数是调用者的属性;调用者不知道 - 也不应该知道 - 对象的动态类型.)