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.
}
Здравствуйте, Аноним, Вы писали:
А>Что за странный пример в 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.
Здравствуйте, Аноним, Вы писали:
А>Что за странный пример в 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 добавить:
Здравствуйте, 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.
Здравствуйте, 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
}
Здравствуйте, 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()
По моим представлениям, using-объявление — это объявление члена, потому оно скрывает fun из B и все правильно. В исходном примере в стандарте говорилось, что такие using объявления должны игнорироваться в случае вирт. функций! Вот в чем загвоздка! Кто нибудь, разъясните!
Of course, the code must be complete enough to compile and link.
Здравствуйте, 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 попробуйте кто-нить, плиз) понимают это одинаково. Может все-таки это я чего не догоняю ?
Здравствуйте, 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 никто и не сомневается.
R>Естественно должны игнорироваться, т.к. виртуальная функция всегда должна вызываться из самого производного класса независимо от контекста вызова (явную спецификацию тут не рассматриваем, не тот случай).
Не спеши насчет естественно. В примере — откровенно неполиморфный вызов C c; c.fun(); и стандарт утверждает, что игнорируется using — объявление — стало быть в примере глюк.
R>А вот щас буит еще смешнее R>Настораживает только то, что и VC6, и VC7.1 (на gcc попробуйте кто-нить, плиз) понимают это одинаково. Может все-таки это я чего не догоняю ?
Действительно не совсем догоняешь. При вызове через ссылки и указатели используется механизм вызова виртуальных функций и тут уж все точно ок.
Of course, the code must be complete enough to compile and link.
Здравствуйте, Lorenzo_LAMAS, Вы писали:
LL>В исходном примере в стандарте говорилось, что такие using объявления должны игнорироваться в случае вирт. функций! Вот в чем загвоздка!
Ну укажи этот пример. Я вот вижу 7.3.3/12, в котором все достаточно доступно: имя из базового класса, введенное using-декларацией, будет скрыто в производном классе переопределением функции с той же сигнатурой, что и в базовом. Покуда переопределения не случилось, ничего никуда не скрывается. И ни слова про исключение для случая с виртуальными функциями.
Здравствуйте, Lorenzo_LAMAS, Вы писали:
L_L>Здравствуйте, Romanch, Вы писали:
R>>Это все, конечно, верно, но вызов c.fun() это тоже полиморфный вызов.
L_L>Нет, это неполиморфный вызов
Т.е. ты утверждаешь, что в контексте нашего примера c.fun() и c.C::fun() одно и то же ?
Хммм... придется лезть в стандарт.
Здравствуйте, Lorenzo_LAMAS, Вы писали:
L_L>Динамическое связывание работает только при использовании ссылок и указателей. В случае с L_L>C c; c.fun(); нужная функция известна на этапе компиляции.
Ладно, тогда я задам другой вопрос — c.fun() и (&c)->fun() одно и то же ?
Кстати, 6й и 7й вижуалы в последнем случае тоже вызывают A::fun
Пункт 10.3 о том и говорит, что даже при вызове виртуальной функции НЕ через указатель, поведение программы должно быть таким, как будто функцию вызвали ЧЕРЕЗ указатель. Собственно, стандарту в этом месте пофиг как вызывают виртуальную ф-ю, для конкретного класса есть единственный final overrider, он и должен вызываться, это и есть полиморфный вызов. А уж как компилятор это реализует в конкретном случае, с использованием таблицы виртуальных функций или без оного, не суть важно.
Вывод, следовательно, такой — и вижуал и gcc на этом примере глючат. Про другие компиляторы кто-нить может рассказать ?
Здравствуйте, Аноним, Вы писали:
А>Что за странный пример в 10.3/2
так написано же: using игнорируются при вызове виртуальной функции.
а при вызове с полной квалификацией виртуальный механизм подавляется.
Пример абсолютно корректен.
Здравствуйте, 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.
Здравствуйте, jazzer, Вы писали:
J>так написано же: using игнорируются при вызове виртуальной функции. J>а при вызове с полной квалификацией виртуальный механизм подавляется. J>Пример абсолютно корректен.
(шепотом) Тогда некорректна работа как минимум 3-х компиляторов в этом месте
Здравствуйте, 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.
Здравствуйте, 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++ было написано, не думаю, что стандарт мог так радикально поменяться.
Здравствуйте, Kaa, Вы писали:
J>>так написано же: using игнорируются при вызове виртуальной функции. J>>а при вызове с полной квалификацией виртуальный механизм подавляется. J>>Пример абсолютно корректен.
Kaa>(шепотом) Тогда некорректна работа как минимум 3-х компиляторов в этом месте
(тоже шепотом) А иначе некорректен пример приведенный в стандарте языка
Вопрос что впереди, телега или лошадь ?
Здравствуйте, Kaa, Вы писали:
Kaa>(0) — Функции, объявленные в в производном классе, скрывают функции из базового класса, которые в противном случае были бы доступны. Достигается using-объявлением.
Это неверно для виртуальных функций. Да и вообще формулировка нехорошая, можно долго и разнообразно придираться :)
R>Компилируя вызов c.fun() компилятор в общем случае ОБЯЗАН воспользоваться таблицей виртуальных функций, именно такое его поведение приведет к игнорированию using для этой конкретной функции. Другое дело, что он МОЖЕТ соптимизировать вызов, зная, что 'С' это most derived класс, компилятор может сгенерить прямой вызов final overrider'а, но уж ни в коем случае не функции объявленной через using. Про это, кажется, в ARM от старой версии C++ было написано, не думаю, что стандарт мог так радикально поменяться.
Именно это и написано в Стандарте прямо над цитируемым примером. (Правда, там не упоминается вмт :) )
Здравствуйте, Romanch, Вы писали:
R>Здравствуйте, Kaa, Вы писали:
J>>>так написано же: using игнорируются при вызове виртуальной функции. J>>>а при вызове с полной квалификацией виртуальный механизм подавляется. J>>>Пример абсолютно корректен.
Kaa>>(шепотом) Тогда некорректна работа как минимум 3-х компиляторов в этом месте :)
R>(тоже шепотом) А иначе некорректен пример приведенный в стандарте языка :) R>Вопрос что впереди, телега или лошадь ? :)
нормативная часть Стандарта впереди примеров, которые являются лишь иллюстрациями.
Но в данном случае я не вижу противоречия примера нормативной части.
Здравствуйте, 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
...
Здравствуйте, 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
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Kaa, Вы писали:
J>> так написано же: using игнорируются при вызове виртуальной функции.
K> (шепотом) Тогда некорректна работа как минимум 3-х компиляторов в этом месте
Да, некорректна. Для успокоения: Visual 7.1, Borland 5.6 и (last but not least) Comeau
работают в этом случае, как указано в примере в стандарте.
Posted via RSDN NNTP Server 1.5 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, 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
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
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
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Lorenzo_LAMAS, Вы писали:
R>> Естественно должны игнорироваться, т.к. виртуальная функция всегда должна R>> вызываться из самого производного класса независимо от контекста вызова
LL> Не спеши насчет естественно. В примере — откровенно неполиморфный вызов C c; c.fun();
Тем не меннее, компилятор обязан вызвать fun из наиболее унаследованного объекта.
Стандарт не дает никакой специальной свободы компилятору в случае неполиморфного вызова.
Posted via RSDN NNTP Server 1.5 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
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 действительно все компилит правильно.
Здравствуйте, Lorenzo_LAMAS, Вы писали:
LL> Кажется начинаю догонять Получается, что виртуальные функции всегда, LL> даже в случае неполиморфного вызова должны вести себя как виртуальные?
Да. Исключение составляет вызов с явным указанием класса, чью функцию нужно вызывать.
Posted via RSDN NNTP Server 1.5 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Облазив весь группогуголь и стандарт, выяснил, что мне показалось неправильно. Однако то, что новий GCC (3.2) выдал результат, аналогичный VC6 98-го года выпуска, меня несколько смутило.
Здравствуйте, Lorenzo_LAMAS, Вы писали:
L_L>Кажется начинаю догонять L_L>Получается, что виртуальные функции всегда, даже в случае неполиморфного вызова должны вести себя как виртуальные?
Нет такого понятия — неполиморфный вызов.
Есть просто вызов (всегда полиморфный для виртуальной функции) и вызов с явной квалификацией (при этом нет вообще понятия "виртуальный" — так написано в Стандарте).
Если ты понимаешь под неполиморфным вызовом вызов без runtime-обращения к vmt, то никто не мешает компилятору сгенерить явный вызов final overrider-a, если ему и так понятно, что именно надо звать (а в обсуждаемом примере именно эта ситуация и есть).
Но это лишь вопрос оптимизации, не более. Идеологически правильно считать, что при отсутствии явной квалификации вызов всегда идет через vmt.
А что там наоптимизирует компилятор — дело десятое, хотя и полезное
Здравствуйте, 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
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Павел Кузнецов, Вы писали:
j>> Есть просто вызов (всегда полиморфный для виртуальной функции) и вызов с явной j>> квалификацией (при этом нет вообще понятия "виртуальный" — так написано в Стандарте).
ПК>Ну почему же? В стандарте написано, что явная квалификация подавляет механизм виртуального вызова:
ПК>
10.3 Explicit qualification with the scope operator (5.1) suppresses the virtual call mechanism.
Это 'suppresses' я и имел в виду под 'нет вообще понятия "виртуальный"' :)
— Мужик, ты чего в ладоши хлопаешь?
— Крокодилов разгоняю!
— Так их же тут нет!
— Потому и нет, что разгоняю...
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();
}
Здравствуйте, , Вы писали:
> А кто вызовется в таком случае? >
> 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
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Т.е. все, что говорилось в примере относилось к случаю вирт.функций из одного базового класса? (т.е. допустим класса А и его виртуальной функции fun независимо от числа подобъектов этого базового класса)?
Of course, the code must be complete enough to compile and link.