final overrider
От: Аноним  
Дата: 18.06.03 13:40
Оценка: 10 (1)
Что за странный пример в 10.3/2

struct A
{
   virtual void fun(){}
};

struct B:virtual public A
{
   void fun(){}
};

struct C:B, virtual A
{
    using A::fun;
};

void foo()
{
   C c;
   c.fun();//Стандарт говорит, что здесь д.б. вызван final overrider
   //это так? а то у меня вызывается A::fun.
}


Исправлена подсветка синтаксиса. -- ПК.
Re: final overrider
От: ikerk  
Дата: 19.06.03 07:07
Оценка:
Что — то проблема не понятна . Вызывается (и должно вызываться) B::fun().
Re: final overrider
От: Lorenzo_LAMAS  
Дата: 19.06.03 09:22
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Что за странный пример в 10.3/2

А>struct A
А>{
А>   virtual void fun(){}
А>};

А>struct B:virtual public A
А>{
А>   void fun(){}
А>};

А>struct C:B, virtual A
А>{
А>    using A::fun;
А>};

А>void foo()
А>{
А>   C c;
А>   c.fun();//Стандарт говорит, что здесь д.б. вызван final overrider
А>   //это так? а то у меня вызывается A::fun.
А>}


Из примера и утверждения в стандарте возникает впечатление, что наличие ключевого слова virtual должно модифицировать правила поиска имен. Т.е. если б fun была невиртуальной, то using — объявление не игнорировалось бы???? Объяснмите, плиз. Потом, если это правда, то как быть с ситуацией, если в базе есть две перегруженных fun одна вирт., другая нет???
Of course, the code must be complete enough to compile and link.
Re: final overrider
От: Romanch  
Дата: 19.06.03 10:09
Оценка: 5 (1)
Здравствуйте, Аноним, Вы писали:

А>Что за странный пример в 10.3/2

А>[ccode]
А>struct A
А>{
А> virtual void fun(){}
А>};

А>struct B:virtual public A

А>{
А> void fun(){}
А>};

А>struct C:B, virtual A

А>{
А> using A::fun;
А>};

А>void foo()

А>{
А> C c;
А> c.fun();//Стандарт говорит, что здесь д.б. вызван final overrider
А> //это так? а то у меня вызывается A::fun.
А>}

Гораздо смешнее этот пример выглядит если в foo добавить:

A* pa = &c;
pa->fun();

Очередной баг в VC6 ?
Re[2]: final overrider
От: Lorenzo_LAMAS  
Дата: 19.06.03 10:28
Оценка:
R>Очередной баг в VC6 ?

Что вызывается?
Of course, the code must be complete enough to compile and link.
Re[3]: final overrider
От: Romanch  
Дата: 19.06.03 10:47
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

R>>Очередной баг в VC6 ?


L_L>Что вызывается?


6-й вижуал

void foo()
{
C c;
A* pa = &c;
c.fun(); // Вот тут вызывается A::fun
pa->fun(); // А вот тут B::fun
}
Re[4]: final overrider
От: Lorenzo_LAMAS  
Дата: 19.06.03 10:53
Оценка:
Здравствуйте, Romanch, Вы писали:

R>Здравствуйте, Lorenzo_LAMAS, Вы писали:


R>>>Очередной баг в VC6 ?


L_L>>Что вызывается?


R>6-й вижуал

R>void foo()
R>{
R>   C c;
R>   A* pa = &c;
R>   c.fun();   // Вот тут вызывается A::fun

   pa->>fun(); // А вот тут B::fun - хехе, так на то и виртуальная функция. Здесь все
// правильно, это и есть final overrider

}
Of course, the code must be complete enough to compile and link.
Re[5]: final overrider
От: Romanch  
Дата: 19.06.03 11:09
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>Здравствуйте, Romanch, Вы писали:


R>>Здравствуйте, Lorenzo_LAMAS, Вы писали:


R>>>>Очередной баг в VC6 ?


L_L>>>Что вызывается?


R>>6-й вижуал

L_L>
R>>void foo()
R>>{
R>>   C c;
R>>   A* pa = &c;
R>>   c.fun();   // Вот тут вызывается A::fun
L_L>
   pa->>>fun(); // А вот тут B::fun - хехе, так на то и виртуальная функция. Здесь все
L_L>// правильно, это и есть final overrider
L_L>
L_L>}

L_L>


Угу, остается ответить на вопрос — почему c.fun() приводит к вызову другой функции.
То что компилятор в этом месте подавляет механизм виртуального вызова понятно, непонятно почему генерится прямой вызов A::fun вместо B::fun. Что-то я сомневаюсь, что так по стандарту положено.

IMHO объяснить это можно так — компилятор обрабатывает using A тупо добавляя A:: к каждому имени из этой области видимости. Например:

namespace A
{
 void fun();
};

void f()
{
  using namespace A;
  fun(); // это место приводится к A::fun
}
Re[2]: final overrider
От: Kaa Украина http://blog.meta.ua/users/kaa/
Дата: 19.06.03 11:11
Оценка: +1 -1
Здравствуйте, Romanch, Вы писали:

R>Очередной баг в VC6 ?

GCC 3.2 подвержен этому "багу" в равной степени

Ситуация, на мой взгляд, такая:

struct A 
{ 
  virtual void fun() {}
}; 

struct B:virtual public A 
{ 
  void fun() {} 
}; 

struct C:B, virtual A 
{ 
  using A::fun; // (0)
}; 

void foo() 
{ 
  C c; 
  c.fun(); // C::fun() == A::fun() (1)

  A* p = &c;
  p->fun(); // полиморфный вызов   (2)
}


(0) — Функции, объявленные в в производном классе, скрывают функции из базового класса, которые в противном случае были бы доступны. Достигается using-объявлением.
(1) — Статический вызов C::A(). (0) Приводит к тому, что вызов с полностью квалифицированным именем C::fun() должен приводить к A::fun(). Все законно.
(2) — полиморфный вызов. вызывает последнюю определенную функцию для A::fun(), т.е. B::fun()
Алексей Кирдин
Re[6]: final overrider
От: Lorenzo_LAMAS  
Дата: 19.06.03 11:17
Оценка:
По моим представлениям, using-объявление — это объявление члена, потому оно скрывает fun из B и все правильно. В исходном примере в стандарте говорилось, что такие using объявления должны игнорироваться в случае вирт. функций! Вот в чем загвоздка! Кто нибудь, разъясните!
Of course, the code must be complete enough to compile and link.
Re[7]: final overrider
От: Romanch  
Дата: 19.06.03 11:31
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>По моим представлениям, using-объявление — это объявление члена, потому оно скрывает fun из B и все правильно. В исходном примере в стандарте говорилось, что такие using объявления должны игнорироваться в случае вирт. функций! Вот в чем загвоздка! Кто нибудь, разъясните!


Естественно должны игнорироваться, т.к. виртуальная функция всегда должна вызываться из самого производного класса независимо от контекста вызова (явную спецификацию тут не рассматриваем, не тот случай).

А вот щас буит еще смешнее

#include <stdio.h>
struct A
{
   virtual void fun(){ printf("A::f\n"); }
};

struct B:virtual public A
{
   virtual void fun(){ printf("B::f\n"); }
};

struct C:B, virtual A
{
    using A::fun;
};

void g(C* pc)
{
 pc->fun();
}

void main()
{
   C c;
   A* pa = &c;
   c.fun();    // A::fun
   g(&c);      // B::fun
   pa->fun();  // B::fun
}


Настораживает только то, что и VC6, и VC7.1 (на gcc попробуйте кто-нить, плиз) понимают это одинаково. Может все-таки это я чего не догоняю ?
Re[3]: final overrider
От: Romanch  
Дата: 19.06.03 11:40
Оценка:
Здравствуйте, Kaa, Вы писали:

Kaa>(0) — Функции, объявленные в в производном классе, скрывают функции из базового класса, которые в противном случае были бы доступны. Достигается using-объявлением.

Kaa>(1) — Статический вызов C::A(). (0) Приводит к тому, что вызов с полностью квалифицированным именем C::fun() должен приводить к A::fun(). Все законно.
Kaa>(2) — полиморфный вызов. вызывает последнюю определенную функцию для A::fun(), т.е. B::fun()

Это все, конечно, верно, но вызов c.fun() это тоже полиморфный вызов. В том что c.C::fun() должно вызывать A::fun никто и не сомневается.
Re[8]: final overrider
От: Lorenzo_LAMAS  
Дата: 19.06.03 11:43
Оценка:
R>Естественно должны игнорироваться, т.к. виртуальная функция всегда должна вызываться из самого производного класса независимо от контекста вызова (явную спецификацию тут не рассматриваем, не тот случай).

Не спеши насчет естественно. В примере — откровенно неполиморфный вызов C c; c.fun(); и стандарт утверждает, что игнорируется using — объявление — стало быть в примере глюк.

R>А вот щас буит еще смешнее

R>Настораживает только то, что и VC6, и VC7.1 (на gcc попробуйте кто-нить, плиз) понимают это одинаково. Может все-таки это я чего не догоняю ?

Действительно не совсем догоняешь. При вызове через ссылки и указатели используется механизм вызова виртуальных функций и тут уж все точно ок.
Of course, the code must be complete enough to compile and link.
Re[4]: final overrider
От: Lorenzo_LAMAS  
Дата: 19.06.03 11:46
Оценка:
Здравствуйте, Romanch, Вы писали:

R>Это все, конечно, верно, но вызов c.fun() это тоже полиморфный вызов.


Нет, это неполиморфный вызов
Of course, the code must be complete enough to compile and link.
Re[7]: final overrider
От: Kaa Украина http://blog.meta.ua/users/kaa/
Дата: 19.06.03 11:53
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

LL>В исходном примере в стандарте говорилось, что такие using объявления должны игнорироваться в случае вирт. функций! Вот в чем загвоздка!

Ну укажи этот пример. Я вот вижу 7.3.3/12, в котором все достаточно доступно: имя из базового класса, введенное using-декларацией, будет скрыто в производном классе переопределением функции с той же сигнатурой, что и в базовом. Покуда переопределения не случилось, ничего никуда не скрывается. И ни слова про исключение для случая с виртуальными функциями.
Алексей Кирдин
Re[5]: final overrider
От: Romanch  
Дата: 19.06.03 12:25
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>Здравствуйте, Romanch, Вы писали:


R>>Это все, конечно, верно, но вызов c.fun() это тоже полиморфный вызов.


L_L>Нет, это неполиморфный вызов


Т.е. ты утверждаешь, что в контексте нашего примера c.fun() и c.C::fun() одно и то же ?
Хммм... придется лезть в стандарт.
Re[6]: final overrider
От: Lorenzo_LAMAS  
Дата: 19.06.03 12:38
Оценка:
Динамическое связывание работает только при использовании ссылок и указателей. В случае с
C c; c.fun(); нужная функция известна на этапе компиляции.
Of course, the code must be complete enough to compile and link.
Re[7]: final overrider
От: Romanch  
Дата: 19.06.03 12:56
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>Динамическое связывание работает только при использовании ссылок и указателей. В случае с

L_L>C c; c.fun(); нужная функция известна на этапе компиляции.

Ладно, тогда я задам другой вопрос — c.fun() и (&c)->fun() одно и то же ?
Кстати, 6й и 7й вижуалы в последнем случае тоже вызывают A::fun

Пункт 10.3 о том и говорит, что даже при вызове виртуальной функции НЕ через указатель, поведение программы должно быть таким, как будто функцию вызвали ЧЕРЕЗ указатель. Собственно, стандарту в этом месте пофиг как вызывают виртуальную ф-ю, для конкретного класса есть единственный final overrider, он и должен вызываться, это и есть полиморфный вызов. А уж как компилятор это реализует в конкретном случае, с использованием таблицы виртуальных функций или без оного, не суть важно.

Вывод, следовательно, такой — и вижуал и gcc на этом примере глючат. Про другие компиляторы кто-нить может рассказать ?
Re: final overrider
От: jazzer Россия Skype: enerjazzer
Дата: 19.06.03 14:04
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Что за странный пример в 10.3/2


так написано же: using игнорируются при вызове виртуальной функции.
а при вызове с полной квалификацией виртуальный механизм подавляется.
Пример абсолютно корректен.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[2]: final overrider
От: Lorenzo_LAMAS  
Дата: 19.06.03 14:08
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Здравствуйте, Аноним, Вы писали:


А>>Что за странный пример в 10.3/2


J>так написано же: using игнорируются при вызове виртуальной функции.

J>а при вызове с полной квалификацией виртуальный механизм подавляется.
J>Пример абсолютно корректен.

Да??? А вот это C c; c.fun()?
А как быть если есть fun и виртуальная и не виртуальная? А если не виртуальная, то не игнорируется?
Я считаю пример некорректным
Of course, the code must be complete enough to compile and link.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.