Russian Qt Forum
Ноябрь 23, 2024, 07:08 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Перекрытие виртуалов [решено]  (Прочитано 5286 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« : Апрель 16, 2014, 12:31 »

Добрый день

Повозившись денек в отладчике пришел к выводу что варнинг "Overloaded virtual functions" лучше все-таки включать. Однако при этом вылазит такой эффект

Код
C++ (Qt)
struct A {
virtual void Test( const QRect & ) { qDebug() << "A::QRect"; }
virtual void Test( const QSize & ) { qDebug() << "A::QSize"; }
};
 
struct B : public A {
virtual void Test( const QRect & ) { qDebug() << "B::QRect"; }
};
 
Получаю варнинг
Цитировать
virtual void A::Test(const QSize&)' was hidden
by 'virtual void B::Test(const QRect&)'
Вопрос: за что? Что я плохого сделал не перекрыв второй виртуал (меня устраивает реализация A), и чем мне это грозит?

Спасибо
« Последнее редактирование: Апрель 17, 2014, 07:53 от Igors » Записан
OKTA
Гость
« Ответ #1 : Апрель 16, 2014, 12:43 »

Потому что компилятор будет смотреть только на названия функций. Параметры он не берет в рассчет, поэтому и предупреждение, т.к. до функции невозможно будет достучаться.
А если добавить using A::Test; в struct B, то тогда компилятор заглянет в A и увидит, что есть еще одна доступная перегруженная ф-ия.
« Последнее редактирование: Апрель 16, 2014, 12:46 от OKTA » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #2 : Апрель 16, 2014, 12:59 »

Потому что компилятор будет смотреть только на названия функций. Параметры он не берет в рассчет, поэтому и предупреждение, т.к. до функции невозможно будет достучаться.
А если добавить using A::Test; в struct B, то тогда компилятор заглянет в A и увидит, что есть еще одна доступная перегруженная ф-ия.
Та ну, "mengled" имя включает параметры. И достучаться из B - пожалуйста. И как он может ее не видеть если B наследуется от A - значит описание A доступно в единице трансляции
Записан
OKTA
Гость
« Ответ #3 : Апрель 16, 2014, 13:20 »

Сравните, что будет если закоментировать uising А. B не сможет достучаться.
Код:
#include <iostream>

using namespace std;
struct A {
    virtual void Test(int i) { cout << "Test A int " << i; }
virtual void Test() { cout << "Test A"; }
};
 
struct B : public A {
    using A::Test;
virtual void Test() { cout << "Test B"; }
};

int main()
{
  
   B bb;
   bb.Test(5);
  
   return 0;
}

Вот объяснение http://en.wikipedia.org/wiki/Argument-dependent_name_lookup
первым запускается поиск по имени без учета аргументов, а с учетом аргументов запускается только если первый ничего не нашел, а в нашем случае, метод Test найден.
« Последнее редактирование: Апрель 16, 2014, 13:25 от OKTA » Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #4 : Апрель 16, 2014, 13:24 »

"mengled"
mAngle name

И достучаться из B - пожалуйста.
Что у вас за компилятор?
Код
C++ (Qt)
#include <QSize>
#include <QRect>
#include <QDebug>
 
struct A {
virtual void Test( const QRect & ) { qDebug() << "A::QRect"; }
virtual void Test( const QSize & ) { qDebug() << "A::QSize"; }
};
 
struct B : public A {
virtual void Test( const QRect &r ) { qDebug() << "B::QRect"; A::Test( r ); }
};
 
int main(int , char *[])
{
A a;
a.Test( QSize() );
a.Test( QRect() );
 
B b;
b.Test( QSize() );
b.Test( QRect() );
 
return 0;
}
 

Цитировать
g++ -c -pipe -g -Wall -W -D_REENTRANT -fPIE -DQT_CORE_LIB -I/usr/lib/qt/mkspecs/linux-g++ -I/usr/include/qt -I/usr/include/qt/QtCore -I. -I. -o main.o main.cpp
main.cpp: In function 'int main(int, char**)':
main.cpp:21:18: error: no matching function for call to 'B::Test(QSize)'
  b.Test( QSize() );
                  ^
main.cpp:21:18: note: candidate is:
main.cpp:11:15: note: virtual void B::Test(const QRect&)
  virtual void Test( const QRect &r ) { qDebug() << "B::QRect"; A::Test( r ); }
               ^
main.cpp:11:15: note:   no known conversion for argument 1 from 'QSize' to 'const QRect&'
« Последнее редактирование: Апрель 16, 2014, 15:52 от Old » Записан
OKTA
Гость
« Ответ #5 : Апрель 16, 2014, 15:04 »

Old, а причина в том, что я привел http://en.wikipedia.org/wiki/Argument-dependent_name_lookup? 
Или в другом  Шокированный?
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #6 : Апрель 16, 2014, 15:10 »

Old, а причина в том, что я привел http://en.wikipedia.org/wiki/Argument-dependent_name_lookup? 
Или в другом  Шокированный?
В этом.
Мейерс по русски: http://www.e-reading.ws/chapter.php/1002058/82/Mayers_-_Effektivnoe_ispolzovanie_CPP.html
Записан
OKTA
Гость
« Ответ #7 : Апрель 16, 2014, 15:57 »

Да, спасибо.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #8 : Апрель 17, 2014, 07:52 »

Да, действительно, компиляторы gcc/icc выдают ошибку. Хотя using A::Test решает проблему, но как-то стремно (какую - ту или эту?)
Спасибо 
Записан
OKTA
Гость
« Ответ #9 : Апрель 17, 2014, 09:28 »

Ту или эту это вы о каких?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #10 : Апрель 17, 2014, 10:27 »

Ту или эту это вы о каких?
О методах Test класса A, их 2. И какую открывает using (или обе) как-то не очень ясно.
Записан
OKTA
Гость
« Ответ #11 : Апрель 17, 2014, 11:20 »

using A::Test всего лишь открывает видимость имени Test и компилятор будет знать, что "хорошо бы заглянуть и в родительский класс" при поиске Test.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.223 секунд. Запросов: 23.