7
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;
}

所以同一个对象直接使用会产生不同的结果,而通过相同类型的指针使用会产生不同的结果!!!

4

3 回答 3

5

标准第 10.3p2 节中的一个示例清楚地表明 using 声明不会覆盖虚函数。

这是一个已知的 g++ 错误

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

于 2011-01-12T14:05:45.837 回答
1

using level1::foo;foo在类中引入了一个level3引用level1::foo.

在用作成员声明的 using-declaration 中,nested-name-specifier 应命名所定义类的基类。这种使用声明引入了通过成员名称查找找到的声明集。

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

反正我不太确定。

于 2011-01-12T14:01:16.080 回答
0

获得 level1 level1 的方法当然是:

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

您的“使用”指令似乎是在通知编译器,如果您有一个 level3 并在其上调用 foo,它应该调用 level1 版本,但它不会将其覆盖到 v-table。

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

于 2011-01-12T14:00:14.560 回答