Автор: LuckLess 19.10.2007, 10:21
ну... начну с кода...
class I
{
public:
virtual void f ()
{
std::cout << "I";
}
};
class B1 : public I
{
public:
void f ()
{
std::cout << "B1";
}
};
class B2 : public I
{
public:
void f ()
{
std::cout << "B2";
}
};
class C : public B1, public B2
{
public:
using B2::f;
};
int main ()
{
C c;
c.f ();
}
я думаю.. многие ожидали бы вывода B2.. но 8-я студия выводит B1
а на саамом деле все еще лучше.. фактически этот код не должен компилироватся так как
Цитата
Then in any well-formed class, for each virtual function
declared in that class or any of its direct or indirect base classes there is a unique final overrider that overrides that
function and every other overrider of that function. 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.
[ Example:
struct A {
virtual void f();
};
struct B : virtual A {
virtual void f();
};
struct C : B , virtual A {
using A::f;
};
void foo () {
C c;
c.f (); / / calls B::f, the final overrider
c.C::f (); / / calls A::f because of the using-declaration
Насколько мне известно ни один компилятор не ведет себя тут правильно.
Ну... как же вызвать B2::f... есть несколько варантов.. и все кривоватые(хотя наследование от
двух классов, которые наследуются от одинокового интерфейса уже наверняка криво) )
Вариант1.
C c;
c.C::f ();
как в примере из стандарта.. согласитесь
не очень удобно так писать - да?)))
Вариант2.
C c;
c.B2::f ();
еще хуже чем вариант1 ))
Вариант3
class C : public B1, public B2
{
public:
void f ()
{
return B2::f ();
}
};
и так для каждой функции..)) тоже не удобно и много лишнего кода.. но зато функцию f можно использовать нормально
C c;
c.f ();
Возможно есть еще варианты... но чтото в голову они не приходят...
Автор: ViGOur 19.10.2007, 10:29
Интересно, а где подобной может понадобиться...
Хотя с другой стороны, подобное использование using было введено, значит где-то может быть и пригодиться.
Автор: Andrew Selivanov 19.10.2007, 10:49
Прикольно
Временно вкрутив себе мозг разработчика МС я поставил следующий эксперимент:
class C : public B2, public B1
{
public:
using B2::f;
};
Как ты думаешь, что выведется на этот раз?
А серьезно - как то это напоминает мне паттерн Адаптер...
Автор: LuckLess 19.10.2007, 10:51
дада.. если пеменять местами B1 и B2 все ок) сам замечал
Автор: LuckLess 19.10.2007, 10:52
Цитата(Andrew Selivanov @ 19.10.2007, 11:49)
А серьезно - как то это напоминает мне паттерн Адаптер...
ну.. там б1 и б2 не должны от одного интерфеса наследоваться...
чесно говоря не могу сообразить где такое наследование можно применить)))
ну... только если взять COM где каждый интерфейс должен быть наследником IUnknown*
Автор: Andrew Selivanov 19.10.2007, 12:00
Гы
Кстати возникла еще мысль, для четкости надо бы виртуально пронаследовать B1, B2 от I, дабы копии не таскать...
Автор: LuckLess 19.10.2007, 13:10
если пронаследовать виртуально - тогда не будет компилироватся уже по другой причине.))) там одной виртуальной функции будет соответствовать два разных переопределения ))
а в стандарте !!unique!! final overrider