2011-03-11 84 views
9

我有这些类:C++多态性与默认参数

class Base 
{ 
    public: 
     virtual void foo(int x = 0) 
     { 
      printf("X = %d", x); 
     } 
}; 

class Derived : public Base 
{ 
    public: 
     virtual void foo(int x = 1) 
     { 
      printf("X = %d", x); 
     } 
};

当我有:

Base* bar = new Derived(); 
bar->foo();

我的输出为 “X = 0” 时,即使FOO称为衍生自,但是当我有:

Derived* bar = new Derived(); 
bar->foo();

我的输出为 “X = 1”。这种行为是否正确? (要从声明类型中选择默认参数值,而不是从实际对象类型中选择它)。这是否打破C++多态性?

它会导致很多问题,如果有人使用虚拟功能,而无需指定的实际功能参数,并使用该函数的默认参数。即使你重载函数

+1

装上去中的printf()这实际上告诉你哪个函数被调用 – Ferruccio 2011-03-11 13:00:42

+0

很明显,被调用的功能派生:: foo的 – Felics 2011-03-11 13:01:14

+0

如何?他们都打印出像“X = value”的东西。您不能使用该值来确定哪个被调用。试着在底部打印“Base:X =%d”,你就可以知道哪一个被调用。 – Ferruccio 2011-03-11 13:10:10

回答

5

默认参数被保留!这种行为是正确的。让我搜索C++标准的参考。从C++标准

§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() 
} 

此外,不仅它的保留,则每次评价函数被调用:

§8.3.6/ 9说

默认参数每个评估 函数调用时间

+0

@Nawaz:复制/粘贴从另一个答案,而不是链接到它并没有真正帮助整体。特别是当别人提供了链接时。 – Jon 2011-03-11 13:06:59

+0

@Jon:复制粘贴哪个答案?你的意思是我从另一个答案复制粘贴?哪个答案? – Nawaz 2011-03-11 13:09:14

+0

@Jon:好的。我现在就说你的答案。但如果你认为它回答了这个问题,那么你应该说它重复话题并投票结束它! – Nawaz 2011-03-11 13:10:32

5

的行为是正确的。退房的回答这个问题作出解释:

Can virtual functions have default parameters?

道德:请客默认参数值的函数签名的一部分,重写虚函数时,不要对其进行修改

+0

@Jon,感谢您的链接,原始答案肯定会得到我的赞赏... – Nim 2011-03-11 13:10:01

+0

@Jon:如果您认为此链接回答问题,那么您应该投票支持关闭此主题,因为它可能会重复! – Nawaz 2011-03-11 13:12:41

+0

@Nawaz:正如我已经说过的那样:这个问题的答案*也回答了这个问题。问题本身*不是*相同。 – Jon 2011-03-11 13:13:26

0

这是C++设计的,我想。

这个多态性是由虚拟表完成的,它在内部使用指向函数的指针,但是参数的默认值并不随函数指针存储,而是在编译阶段绑定的,所以它只能通过第一个获得默认值看它的类型,在你的第一种情况下,它是Base,然后它使用0作为默认值。

+0

这在技术上是正确的,但误导为答案,因为C++标准没有要求vtables实现多态。它具体说明在这种情况下应该发生什么;如果它将未定义的实现细节留下,那么任何人都可以编写一个符合标准的编译器,该编译器使用像vtable这样的机制来绑定默认值。 – Jon 2011-03-11 13:05:47

+0

是的。但对于那些从事标准工作的人来说,他们也会考虑功能是否实用。我只是认为它是以这种方式设计的,因为另一种方式是不实际的。任何函数都可以有很多参数,所有参数都可以有默认值。这使得运行时绑定一个不可能的任务 – Shuo 2011-03-11 13:55:05