crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

 
Ответить в данную темуНачать новую тему
> Ошибка компилятора в хитрой ситуЁвине
LuckLess
  опции профиля:
сообщение 19.10.2007, 10:21
Сообщение #1


Студент
*

Группа: Новичок
Сообщений: 31
Регистрация: 10.10.2007
Пользователь №: 8

Спасибо сказали: 0 раз(а)




Репутация:   0  


ну... начну с кода...
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 :D

а на саамом деле все еще лучше.. фактически этот код не должен компилироватся так как
Цитата
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 ();
как в примере из стандарта.. согласитесь :p не очень удобно так писать - да?)))

Вариант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
Сообщение #2


Мастер
******

Группа: Модератор
Сообщений: 3296
Регистрация: 9.10.2007
Из: Москва
Пользователь №: 4

Спасибо сказали: 231 раз(а)




Репутация:   40  


Интересно, а где подобной может понадобиться... :)
Хотя с другой стороны, подобное использование using было введено, значит где-то может быть и пригодиться.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Andrew Selivanov
  опции профиля:
сообщение 19.10.2007, 10:49
Сообщение #3


Участник
**

Группа: Участник
Сообщений: 249
Регистрация: 9.10.2007
Из: Москва
Пользователь №: 3

Спасибо сказали: 15 раз(а)




Репутация:   6  


Прикольно :D

Временно вкрутив себе мозг разработчика МС я поставил следующий эксперимент:
class C : public B2, public B1
   {
public:
    using B2::f;
   };


Как ты думаешь, что выведется на этот раз? ;)

А серьезно - как то это напоминает мне паттерн Адаптер...
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
LuckLess
  опции профиля:
сообщение 19.10.2007, 10:51
Сообщение #4


Студент
*

Группа: Новичок
Сообщений: 31
Регистрация: 10.10.2007
Пользователь №: 8

Спасибо сказали: 0 раз(а)




Репутация:   0  


дада.. если пеменять местами B1 и B2 все ок) сам замечал :D
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
LuckLess
  опции профиля:
сообщение 19.10.2007, 10:52
Сообщение #5


Студент
*

Группа: Новичок
Сообщений: 31
Регистрация: 10.10.2007
Пользователь №: 8

Спасибо сказали: 0 раз(а)




Репутация:   0  


Цитата(Andrew Selivanov @ 19.10.2007, 11:49) *
А серьезно - как то это напоминает мне паттерн Адаптер...


ну.. там б1 и б2 не должны от одного интерфеса наследоваться...

чесно говоря не могу сообразить где такое наследование можно применить)))
ну... только если взять COM где каждый интерфейс должен быть наследником IUnknown*
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Andrew Selivanov
  опции профиля:
сообщение 19.10.2007, 12:00
Сообщение #6


Участник
**

Группа: Участник
Сообщений: 249
Регистрация: 9.10.2007
Из: Москва
Пользователь №: 3

Спасибо сказали: 15 раз(а)




Репутация:   6  


Гы :rolleyes:


Кстати возникла еще мысль, для четкости надо бы виртуально пронаследовать B1, B2 от I, дабы копии не таскать...
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
LuckLess
  опции профиля:
сообщение 19.10.2007, 13:10
Сообщение #7


Студент
*

Группа: Новичок
Сообщений: 31
Регистрация: 10.10.2007
Пользователь №: 8

Спасибо сказали: 0 раз(а)




Репутация:   0  


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

а в стандарте !!unique!! final overrider :D
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 28.3.2024, 17:54