应用声明是否应该隐藏继承的虚函数?

时间:2011-01-12 13:53:41

标签: c++ inheritance gcc icc using-declaration

struct level0
{
  virtual void foo() = 0;
};

struct level1 : level0
{
  virtual void foo() { cout <<" level1  " << endl; }
};

struct level2 : level1
{
  virtual void foo() { cout <<" level2 " << endl; }
};

struct level3 : level2
{
  using level1::foo;
};

int main()
{
  level1* l1 = new level3;
  l1->foo();
  level3 l3;
  l3.foo();
  return 0;
}

上面的代码使用gcc给出

level2
level1

但在icc中给出了

 level2
 level2

哪一个是正确的还是标准未定义?

编辑: 这证明存在一个错误,请考虑以下主要功能

int main()
{
    level3 l3;
    l3.foo();               // This prints level1

    level3* pl3 = &l3;
    pl3->foo();             // This prints level2

    level3& rl3 = l3;
    rl3.foo();              // This prints level1

    level3& rpl3 = *pl3;
    rpl3.foo();             // This prints level2

    return 0;
}

因此,直接使用同一个对象会产生不同的结果,当通过相同类型的指针使用时会产生不同的结果!!!

3 个答案:

答案 0 :(得分:5)

标准部分10.3p2中的一个示例清楚地表明,使用声明覆盖虚拟函数。

这是known g++ bug

正如您所注意到的,当通过引用或指针调用成员函数时,而不是已知动态类型的情况,错误不会发生。

答案 1 :(得分:1)

using level1::foo;foo类中引入level3函数,该函数引用level1::foo

  

在用作成员声明的using声明中,嵌套名称指定者应命名要定义的类的基类。这样的using声明引入了由成员名称查找找到的声明集。

但是,由于level1::foo是虚拟的,我想通过调用它你应该调用level2::foo,因此icc应该是正确的。

无论如何,我不太确定。

答案 2 :(得分:0)

获得level1 level1的方法当然是:

struct level3 : level2
{
   virtual void foo() { level1::foo(); }
};

你的“using”指令似乎告诉编译器如果你有一个level3并且在它上面调用foo,它应该调用level1版本,但它不会覆盖到v-table。

gcc由于不一致而看起来不对,不确定icc因为我不知道标准表示什么。