我正在阅读Stroustrup的C ++ 0x FAQ,并坚持使用此代码。请考虑以下代码

struct A
{
    void f(double)
    {
        std::cout << "in double" << std::endl;
    }
};

struct B : A
{
    void f(int)
    {
        std::cout << "in int" << std::endl;
    }
};


int main()
{
    A a; a.f(10.10);  // as expected, A.f will get called
    B b; b.f(10.10);  // This calls b.f and we lose the .10 here
    return 0;
}

我的理解是当一个类型被继承时,所有受保护的和公共成员都可以从派生类访问。但根据这个例子,看起来我错了。我期待 b.f 将调用基类 f 。我通过改变派生类来获得预期的结果,如

struct B : A
{
    using A::f;
    void f(int)
    {
        std::cout << "in int" << std::endl;
    }
};

问题

  1. 为什么它不在第一个代码中工作?
  2. C ++标准中的哪个部分描述了所有这些范围规则?
有帮助吗?

解决方案

第一个代码可以工作,因为c ++可以工作。

重载分辨率遵循一组非常复杂的规则。从Stroustrup的c ++圣经15.2.2“[A]来自不同基类的函数之间的模糊不能基于参数类型来解决。”

他接着解释了“使用”的用法。正如你所描述的那样。

这是该语言的设计决定。

我倾向于遵循Stroustrup书而不是标准书,但我确信它就在那里。

[编辑]

这是(来自标准):

第13章

如果为同一范围内的单个名称指定了两个或更多不同的声明,则说该名称为 超载。

然后:

13.2声明匹配

1如果两个函数声明属于同一作用域且具有等效的参数声明(13.1),则它们引用相同的函数。派生类的函数成员与函数成员的范围不同 基类中的相同名称。

其他提示

因为A :: f是“隐藏”的而不是“超载”或“被覆盖”。参阅:

http://www.parashift.com /c++-faq-lite/strange-inheritance.html#faq-23.9

搜索重载决策类似但不完全相同的问题

在C ++中,范围内没有重载,派生类中的范围也不例外。 (根据C ++编程语言)

有关详细信息,请查看 http://www.research。 att.com/~bs/bs_faq2.html#overloadderived

在第一种情况下,派生类方法的基类方法'f'是隐藏。在C ++中,范围内没有超载;这就是它没有被召唤的原因。 C ++标准解释了 部分10.2成员名称查找[class.member.lookup] 中的所有成员名称查找规则。 HTH

第一个版本的代码应该真正调用B :: f。您重新定义符号“f”。在结构“B”中,它隐藏了原始符号“f”。来自struct“A”。它看起来并不是一种过载。

每当编译器遇到b.f()时,它就会搜索“B”。符号“f”的结构。它存在于那里,因此编译器决定调用B :: f(int),将double转换为int。它认为不需要扫描父类以获得更合适的函数......

然而,当你添加“使用A :: f”时,它是一个explict指令,编译器扫描父类的符号“f”。现在,B类有两个重载函数:for int和for double。

我也相信,你可以在不使用“使用”的情况下编写b.A :: f()。原始例子中的指令......

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top