Предполагается ли использование декларации скрыть унаследованную виртуальную функцию?

StackOverflow https://stackoverflow.com/questions/4669524

Вопрос

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

Таким образом, один и тот же объект, когда используется непосредственно, дает разные результаты и при использовании через указатель того же типа дает разные результаты !!!

Это было полезно?

Решение

Пример в стандартном разделе 10.3p2 дает понять, что использование объявлений делает нет переопределить виртуальные функции.

Это Известная ошибка G ++.

Как вы заметили, при вызове функции элемента через ссылку или указатель, а не случай, когда динамический тип известен, ошибка не происходит.

Другие советы

using level1::foo; представляет foo функционировать в level3 класс, который относится к level1::foo.

При использовании декларации, используемого в качестве декларации члена, вложенная имен-специфическая должна назвать базовый класс, определяемый классом. Такое использование декларации вводит набор объявлений, найденных по имени участника.

Однако, поскольку level1::foo виртуально, я думаю, что, позвонив, вы должны позвонить level2::foo, таким образом, ICC должен быть прав.

Я не уверен, в любом случае.

Способ получить уровень 1 уровня1, конечно, будет:

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

Ваша директива «Использование», кажется, информирует компилятора, что если у вас есть уровень 3 и вызовать Foo на ней, она должна вызывать версию Level1, но это не перезаписывает это на V-таблице.

GCC выглядит неправильно из -за несоответствия, не уверен в ICC, потому что я не знаю, что указывает стандарт.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top