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.
Re[2]: final overrider
От: Kaa Украина http://blog.meta.ua/users/kaa/
Дата: 19.06.03 14:10
Оценка:
Здравствуйте, jazzer, Вы писали:

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

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

(шепотом) Тогда некорректна работа как минимум 3-х компиляторов в этом месте
Алексей Кирдин
Re[3]: final overrider
От: jazzer Россия Skype: enerjazzer
Дата: 19.06.03 14:29
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

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


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


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


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

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

L_L>Да??? А вот это C c; c.fun()?

L_L>А как быть если есть fun и виртуальная и не виртуальная? А если не виртуальная, то не игнорируется?
L_L>Я считаю пример некорректным

А где тут виртуальные и невиртуальные???
я вижу только одну виртуальную функцию, объявленную в А и перекрытую в B.
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[3]: final overrider
От: Romanch  
Дата: 19.06.03 14:35
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

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


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

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

L_L>Да??? А вот это C c; c.fun()?

L_L>А как быть если есть fun и виртуальная и не виртуальная? А если не виртуальная, то не игнорируется?

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

L_L>Я считаю пример некорректным


А я считаю некорректым поведение компиляторов на этом примере.

Компилируя вызов c.fun() компилятор в общем случае ОБЯЗАН воспользоваться таблицей виртуальных функций, именно такое его поведение приведет к игнорированию using для этой конкретной функции. Другое дело, что он МОЖЕТ соптимизировать вызов, зная, что 'С' это most derived класс, компилятор может сгенерить прямой вызов final overrider'а, но уж ни в коем случае не функции объявленной через using. Про это, кажется, в ARM от старой версии C++ было написано, не думаю, что стандарт мог так радикально поменяться.
Re[3]: final overrider
От: Romanch  
Дата: 19.06.03 14:37
Оценка:
Здравствуйте, Kaa, Вы писали:

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

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

Kaa>(шепотом) Тогда некорректна работа как минимум 3-х компиляторов в этом месте


(тоже шепотом) А иначе некорректен пример приведенный в стандарте языка
Вопрос что впереди, телега или лошадь ?
Re[3]: final overrider
От: jazzer Россия Skype: enerjazzer
Дата: 19.06.03 14:41
Оценка:
Здравствуйте, Kaa, Вы писали:

Kaa>(0) — Функции, объявленные в в производном классе, скрывают функции из базового класса, которые в противном случае были бы доступны. Достигается 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[4]: final overrider
От: jazzer Россия Skype: enerjazzer
Дата: 19.06.03 14:43
Оценка:
Здравствуйте, Romanch, Вы писали:



R>Компилируя вызов c.fun() компилятор в общем случае ОБЯЗАН воспользоваться таблицей виртуальных функций, именно такое его поведение приведет к игнорированию using для этой конкретной функции. Другое дело, что он МОЖЕТ соптимизировать вызов, зная, что 'С' это most derived класс, компилятор может сгенерить прямой вызов final overrider'а, но уж ни в коем случае не функции объявленной через using. Про это, кажется, в ARM от старой версии C++ было написано, не думаю, что стандарт мог так радикально поменяться.


Именно это и написано в Стандарте прямо над цитируемым примером. (Правда, там не упоминается вмт :) )
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[4]: final overrider
От: jazzer Россия Skype: enerjazzer
Дата: 19.06.03 14:45
Оценка:
Здравствуйте, Romanch, Вы писали:

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


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

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

Kaa>>(шепотом) Тогда некорректна работа как минимум 3-х компиляторов в этом месте :)


R>(тоже шепотом) А иначе некорректен пример приведенный в стандарте языка :)

R>Вопрос что впереди, телега или лошадь ? :)

нормативная часть Стандарта впереди примеров, которые являются лишь иллюстрациями.
Но в данном случае я не вижу противоречия примера нормативной части.
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[5]: final overrider
От: Romanch  
Дата: 19.06.03 14:56
Оценка:
Здравствуйте, jazzer, Вы писали:

R>>Компилируя вызов c.fun() компилятор в общем случае ОБЯЗАН воспользоваться таблицей виртуальных функций, именно такое его поведение приведет к игнорированию using для этой конкретной функции. Другое дело, что он МОЖЕТ соптимизировать вызов, зная, что 'С' это most derived класс, компилятор может сгенерить прямой вызов final overrider'а, но уж ни в коем случае не функции объявленной через using. Про это, кажется, в ARM от старой версии C++ было написано, не думаю, что стандарт мог так радикально поменяться.


J>Именно это и написано в Стандарте прямо над цитируемым примером. (Правда, там не упоминается вмт )


Во ! Золотые слова !
Но проблема в том, что 3 (три!) компилятора, VC6, VC7 и g++, неправильно компилируют этот пример. Там, где в стандарте написано
...
  c.f(); // calls B::f(), the final overrider
...


вызывается почему-то A::f()
Re[2]: final overrider
От: Павел Кузнецов  
Дата: 19.06.03 15:48
Оценка: 3 (1)
Здравствуйте, Lorenzo_LAMAS, Вы писали:

А>> Что за странный пример в 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.
А>> }
А>>


LL> Из примера и утверждения в стандарте возникает впечатление, что наличие

LL> ключевого слова virtual должно модифицировать правила поиска имен.

Так и есть.

The rules for member lookup (10.2) are used to determine the final overrider for a virtual
function in the scope of a derived class but ignoring names introduced by using-declarations.


LL> Т.е. если б fun была невиртуальной, то using — объявление не игнорировалось бы????


Да. Если бы функция fun была бы невиртуальной, в обоих случаях была бы вызвана A::fun,
т.к. это явно указано путем использования using-declaration.

LL> Объяснмите, плиз.


А что тут объяснять-то? Если бы не было специального правила для виртуальных функций, получалось
бы, то, что наблюдается в старых версиях VC и в GCC: "виртуальные невиртуальные функции".

LL> Потом, если это правда, то как быть с ситуацией, если в базе

LL> есть две перегруженных fun одна вирт., другая нет???

Соответственно:

#include <iostream>

struct A
{
  virtual void fun(int) { std::cout << "A::fun(int)" << std::endl;   }
  void fun(float)       { std::cout << "A::fun(float)" << std::endl; }
};

struct B : virtual A
{
  void fun(int)   { std::cout << "B::fun(int)" << std::endl; }
  void fun(float) { std::cout << "B::fun(float)" << std::endl; }
};

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

int main()
{
  C c;
  c.fun(10);    // B::fun(int)
  c.fun(1.0f);  // A::fun(float)

  A* p = &c;
  p->fun(10);   // B::fun(int)
  p->fun(1.0f); // A::fun(float)
}


> como main_nv.cpp
Comeau C/C++ 4.3.0.1 (Aug 21 2002 15:45:32) for MS_WINDOWS_x86
Copyright 1988-2002 Comeau Computing.  All rights reserved.
MODE:strict warnings C++

> aout
B::fun(int)
A::fun(float)
B::fun(int)
A::fun(float)


> cl /GX main_nv.cpp
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.3077 for 80x86
Copyright (C) Microsoft Corporation 1984-2002. All rights reserved.

main_nv.cpp
Microsoft (R) Incremental Linker Version 7.10.3077
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:main_nv.exe
main_nv.obj

> main_nv
B::fun(int)
A::fun(float)
B::fun(int)
A::fun(float)


> bcc32 main_nv.cpp
Borland C++ 5.6 for Win32 Copyright (c) 1993, 2002 Borland
main_nv.cpp:
Turbo Incremental Link 5.60 Copyright (c) 1997-2002 Borland

> main_nv
B::fun(int)
A::fun(float)
B::fun(int)
A::fun(float)
Posted via RSDN NNTP Server 1.5 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[3]: final overrider
От: Павел Кузнецов  
Дата: 19.06.03 16:00
Оценка:
Здравствуйте, Kaa, Вы писали:

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


K> (шепотом) Тогда некорректна работа как минимум 3-х компиляторов в этом месте


Да, некорректна. Для успокоения: Visual 7.1, Borland 5.6 и (last but not least) Comeau
работают в этом случае, как указано в примере в стандарте.
Posted via RSDN NNTP Server 1.5 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[3]: final overrider
От: Павел Кузнецов  
Дата: 19.06.03 16:00
Оценка:
Здравствуйте, Kaa, Вы писали:

K> (1) — Статический вызов C::A(). (0) Приводит к тому, что вызов с полностью

K> квалифицированным именем C::fun() должен приводить к A::fun(). Все законно.

С той только разницей, что т.к. функция виртуальна, результаты должны быть такие же, как и в (2).

K> (2) — полиморфный вызов. вызывает последнюю определенную функцию для A::fun(), т.е. B::fun()
Posted via RSDN NNTP Server 1.5 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[8]: final overrider
От: Павел Кузнецов  
Дата: 19.06.03 16:00
Оценка:
Здравствуйте, Romanch, Вы писали:

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

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

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

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

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


R> Настораживает только то, что и VC6, и VC7.1 <...> понимают это одинаково.


Ты ничего не перепутал? Именно VC7.1? У меня VC7.1 выдает то, что и ожидается:

> cl main2.cpp
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.3077 for 80x86
Copyright (C) Microsoft Corporation 1984-2002. All rights reserved.

main2.cpp
Microsoft (R) Incremental Linker Version 7.10.3077
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:main2.exe
main2.obj

> main2
B::f
B::f
B::f
Posted via RSDN NNTP Server 1.5 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[9]: final overrider
От: Павел Кузнецов  
Дата: 19.06.03 16:07
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

R>> Естественно должны игнорироваться, т.к. виртуальная функция всегда должна

R>> вызываться из самого производного класса независимо от контекста вызова

LL> Не спеши насчет естественно. В примере — откровенно неполиморфный вызов C c; c.fun();


Тем не меннее, компилятор обязан вызвать fun из наиболее унаследованного объекта.
Стандарт не дает никакой специальной свободы компилятору в случае неполиморфного вызова.
Posted via RSDN NNTP Server 1.5 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[9]: final overrider
От: Romanch  
Дата: 19.06.03 16:24
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:


R>> Настораживает только то, что и VC6, и VC7.1 <...> понимают это одинаково.


ПК>Ты ничего не перепутал? Именно VC7.1? У меня VC7.1 выдает то, что и ожидается:


ПК>
>> cl main2.cpp
ПК>Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.3077 for 80x86
ПК>Copyright (C) Microsoft Corporation 1984-2002. All rights reserved.

ПК>main2.cpp
ПК>Microsoft (R) Incremental Linker Version 7.10.3077
ПК>Copyright (C) Microsoft Corporation.  All rights reserved.

ПК>/out:main2.exe
ПК>main2.obj

>> main2
ПК>B::f
ПК>B::f
ПК>B::f
ПК>


Угу, сори, таки перепутал, то 7.0 был. 7.1 действительно все компилит правильно.
Re[3]: final overrider
От: Lorenzo_LAMAS  
Дата: 20.06.03 07:05
Оценка:
Кажется начинаю догонять
Получается, что виртуальные функции всегда, даже в случае неполиморфного вызова должны вести себя как виртуальные?
Of course, the code must be complete enough to compile and link.
Re[4]: final overrider
От: Павел Кузнецов  
Дата: 20.06.03 07:36
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

LL> Кажется начинаю догонять Получается, что виртуальные функции всегда,

LL> даже в случае неполиморфного вызова должны вести себя как виртуальные?

Да. Исключение составляет вызов с явным указанием класса, чью функцию нужно вызывать.
Posted via RSDN NNTP Server 1.5 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[3]: final overrider
От: Kaa Украина http://blog.meta.ua/users/kaa/
Дата: 20.06.03 08:45
Оценка:
Здравствуйте, Kaa, Вы писали:

Облазив весь группогуголь и стандарт, выяснил, что мне показалось неправильно. Однако то, что новий GCC (3.2) выдал результат, аналогичный VC6 98-го года выпуска, меня несколько смутило.

Мое предыщущее сообщение считать неверным.
Алексей Кирдин
Re[4]: final overrider
От: Lorenzo_LAMAS  
Дата: 20.06.03 08:50
Оценка:
Kaa>Однако то, что новий GCC (3.2) выдал результат, аналогичный VC6 98-го года выпуска, меня несколько смутило.

На то он и бесплатный
Of course, the code must be complete enough to compile and link.
Re[4]: final overrider
От: jazzer Россия Skype: enerjazzer
Дата: 20.06.03 08:58
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>Кажется начинаю догонять

L_L>Получается, что виртуальные функции всегда, даже в случае неполиморфного вызова должны вести себя как виртуальные?

Нет такого понятия — неполиморфный вызов.
Есть просто вызов (всегда полиморфный для виртуальной функции) и вызов с явной квалификацией (при этом нет вообще понятия "виртуальный" — так написано в Стандарте).

Если ты понимаешь под неполиморфным вызовом вызов без runtime-обращения к vmt, то никто не мешает компилятору сгенерить явный вызов final overrider-a, если ему и так понятно, что именно надо звать (а в обсуждаемом примере именно эта ситуация и есть).

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

А что там наоптимизирует компилятор — дело десятое, хотя и полезное
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[5]: final overrider
От: Павел Кузнецов  
Дата: 20.06.03 09:33
Оценка:
Здравствуйте, jazzer, Вы писали:

j> Нет такого понятия — неполиморфный вызов.


Зато есть понятие virtual function call, или, в некоторых местах, virtual call.

j> Есть просто вызов (всегда полиморфный для виртуальной функции) и вызов с явной

j> квалификацией (при этом нет вообще понятия "виртуальный" — так написано в Стандарте).

Ну почему же? В стандарте написано, что явная квалификация подавляет механизм виртуального вызова:

10.3 Explicit qualification with the scope operator (5.1) suppresses the virtual call mechanism.

Posted via RSDN NNTP Server 1.5 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[4]: final overrider
От: Kaa Украина http://blog.meta.ua/users/kaa/
Дата: 20.06.03 09:38
Оценка:
Здравствуйте, Romanch, Вы писали:

R>Вопрос что впереди, телега или лошадь ?

Выяснили, что все-же лошадь. Все остальные варианты — заблуждения.
Алексей Кирдин
Re[6]: final overrider
От: jazzer Россия Skype: enerjazzer
Дата: 20.06.03 10:50
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

j>> Есть просто вызов (всегда полиморфный для виртуальной функции) и вызов с явной

j>> квалификацией (при этом нет вообще понятия "виртуальный" — так написано в Стандарте).

ПК>Ну почему же? В стандарте написано, что явная квалификация подавляет механизм виртуального вызова:


ПК>

10.3 Explicit qualification with the scope operator (5.1) suppresses the virtual call mechanism.


Это 'suppresses' я и имел в виду под 'нет вообще понятия "виртуальный"' :)
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[7]: final overrider
От: Павел Кузнецов  
Дата: 20.06.03 11:56
Оценка:
Здравствуйте, jazzer, Вы писали:

ПК>>

10.3 Explicit qualification with the scope operator (5.1)
ПК>> suppresses the virtual call mechanism.


j> Это 'suppresses' я и имел в виду под 'нет вообще понятия "виртуальный"'


Так как же она может подавлять то, чего нет?
Posted via RSDN NNTP Server 1.5 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[8]: final overrider
От: jazzer Россия Skype: enerjazzer
Дата: 20.06.03 12:13
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>Здравствуйте, jazzer, Вы писали:


ПК>>>

10.3 Explicit qualification with the scope operator (5.1)
ПК>>> suppresses the virtual call mechanism.


j>> Это 'suppresses' я и имел в виду под 'нет вообще понятия "виртуальный"' :)


ПК>Так как же она может подавлять то, чего нет? :))


Наоборот, она подавила и теперь ничего нет :))
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[9]: final overrider
От: Павел Кузнецов  
Дата: 20.06.03 12:21
Оценка:
Здравствуйте, jazzer, Вы писали:

ПК>> Так как же она может подавлять то, чего нет?


j> Наоборот, она подавила и теперь ничего нет


А когда нет явной квалификации, которая подавляет то, чего нет,
все-таки остается virtual function call Ладно... Это уже детали...
Posted via RSDN NNTP Server 1.5 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[10]: final overrider
От: Дмитрий Наумов  
Дата: 20.06.03 13:32
Оценка: :)
Здравствуйте, Павел Кузнецов, Вы писали:

— Мужик, ты чего в ладоши хлопаешь?
— Крокодилов разгоняю!
— Так их же тут нет!
— Потому и нет, что разгоняю...
Re[3]: final overrider
От: Аноним  
Дата: 23.06.03 12:55
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:
[]

А кто вызовется в таком случае?
class A
{
public:
    virtual void fun();
};

class A1
{
public:
    virtual void fun();
};

class B:public A
{
public:
    void fun();
};

class C:public A1
{
public:
};

class D:public B, public C
{
public:
    using C::fun;
};

void g()
{
    D d;
    d.fun();
}
Re[4]: final overrider
От: Павел Кузнецов  
Дата: 24.06.03 11:14
Оценка:
Здравствуйте, , Вы писали:

> А кто вызовется в таком случае?

>
> class A {
> public:
>     virtual void fun();

> class A1 {
> public:
>     virtual void fun();

> class B:public A {
> public:
>     void fun();

> class C:public A1 {

> class D:public B, public C {
> public:
>     using C::fun;

> D d;
> d.fun();
>


A1::fun. Без "using C::fun;" в классе D была бы неоднозначность,
а так мы явно говорим, какую функцию следует вызывать.
Posted via RSDN NNTP Server 1.5 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[5]: final overrider
От: Lorenzo_LAMAS  
Дата: 24.06.03 11:17
Оценка:
Т.е. все, что говорилось в примере относилось к случаю вирт.функций из одного базового класса? (т.е. допустим класса А и его виртуальной функции fun независимо от числа подобъектов этого базового класса)?
Of course, the code must be complete enough to compile and link.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.