继承时的范围规则 - C ++

时间:2009-06-17 08:28:14

标签: c++ scope

我正在阅读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 ++标准中的哪个部分描述了所有这些范围规则?

6 个答案:

答案 0 :(得分:5)

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

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

答案 1 :(得分:4)

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

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

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

这是该语言的设计决定。

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

[编辑]

这是(来自标准):

第13章

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

然后:

13.2声明匹配

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

答案 2 :(得分:2)

搜索重载决策。一个similar, but not identical question

答案 3 :(得分:1)

在C ++中,范围内没有重载,派生类中的范围也不例外。 (According to The C++ Programming Language)

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

答案 4 :(得分:1)

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

答案 5 :(得分:1)

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

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

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

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