[dcl.fct.default] / 10中的明显矛盾

时间:2017-05-22 21:34:37

标签: c++ language-lawyer

[dcl.fct.default]/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]

除了上面强调的声明之外,该段落和示例对我来说都很清楚。当我读到这篇文章时,我得到的印象是它与段落的第一部分相矛盾,即虚函数调用使用由静态类型确定的虚函数声明中的默认参数。表示对象的指针或引用。

2 个答案:

答案 0 :(得分:4)

他们并不矛盾,因为他们指的是不同的东西。

  

虚函数调用(10.3)使用由表示对象的指针或引用的静态类型确定的虚函数声明中的默认参数。

这意味着以下内容:

#include <iostream>

struct Base
{
   virtual void foo(int x = 3) { std::cerr << x << '\n'; }
};

struct Derived : Base
{
   virtual void foo(int x = 4) { std::cerr << x << '\n'; }
};

int main()
{
   Derived d;
   Base* ptr = &d;
   ptr->foo(); // prints 3, not 4
}

live demo

  

派生类中的重写函数不会从它覆盖的函数中获取默认参数。

另一方面,这意味着以下内容:

#include <iostream>

struct Base
{
   virtual void foo(int x = 3) { std::cerr << x << '\n'; }
};

struct Derived : Base
{
   virtual void foo(int x) { std::cerr << x << '\n'; }
};

int main()
{
   Derived d;
   d.foo(); // doesn't compile; missing value for x
}

live demo

  

我得到的印象是它与段落的第一部分相矛盾,即虚函数调用使用虚函数声明中的默认参数,该声明由指针或表示对象的引用的静态类型确定。

不。这意味着如果通过其Base接口访问对象,您将获得Base的默认参数...并且如果您通过其Derived接口访问该对象,那么Derived它没有自己的默认参数,你不会获得Base。同一枚硬币的两个非常不同的一面。

而且,公平地说,引用的标准文本给出了完全相同的例子。

答案 1 :(得分:0)

这意味着派生类中的函数可以有自己的默认参数,也可以都没有默认参数。

例如

struct A {
    virtual void f(int a = 7)
    {
        std::cout << "F(" << a << ")" << std::endl;
    }
};
struct B : public A {
    void f(int a = 10)
    {
        std::cout << "F(" << a << ")" << std::endl;
    }
};

B* pb = new B;
A* pa = pb;
pa->f(); // OK, calls pa->B::f(7)
pb->f(); // OK, calls pa->B::f(10)

在第一个电话中

pa->f(); // OK, calls pa->B::f(7)

根据指针pa的静态类型使用函数f的声明的默认参数,该指针是类A中函数的声明。

在第二个电话中

pb->f(); // OK, calls pa->B::f(10)

根据指针pb的静态类型使用函数f声明的默认参数,该指针是B类函数的声明。