Russian Qt Forum

Программирование => С/C++ => Тема начата: Igors от Апрель 16, 2014, 12:31



Название: Перекрытие виртуалов [решено]
Отправлено: Igors от Апрель 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), и чем мне это грозит?

Спасибо


Название: Re: Перекрытие виртуалов
Отправлено: OKTA от Апрель 16, 2014, 12:43
Потому что компилятор будет смотреть только на названия функций. Параметры он не берет в рассчет, поэтому и предупреждение, т.к. до функции невозможно будет достучаться.
А если добавить using A::Test; в struct B, то тогда компилятор заглянет в A и увидит, что есть еще одна доступная перегруженная ф-ия.


Название: Re: Перекрытие виртуалов
Отправлено: Igors от Апрель 16, 2014, 12:59
Потому что компилятор будет смотреть только на названия функций. Параметры он не берет в рассчет, поэтому и предупреждение, т.к. до функции невозможно будет достучаться.
А если добавить using A::Test; в struct B, то тогда компилятор заглянет в A и увидит, что есть еще одна доступная перегруженная ф-ия.
Та ну, "mengled" имя включает параметры. И достучаться из B - пожалуйста. И как он может ее не видеть если B наследуется от A - значит описание A доступно в единице трансляции


Название: Re: Перекрытие виртуалов
Отправлено: OKTA от Апрель 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 найден.


Название: Re: Перекрытие виртуалов
Отправлено: Old от Апрель 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&'


Название: Re: Перекрытие виртуалов
Отправлено: OKTA от Апрель 16, 2014, 15:04
Old, а причина в том, что я привел http://en.wikipedia.org/wiki/Argument-dependent_name_lookup? 
Или в другом  :o?


Название: Re: Перекрытие виртуалов
Отправлено: Old от Апрель 16, 2014, 15:10
Old, а причина в том, что я привел http://en.wikipedia.org/wiki/Argument-dependent_name_lookup? 
Или в другом  :o?
В этом.
Мейерс по русски: http://www.e-reading.ws/chapter.php/1002058/82/Mayers_-_Effektivnoe_ispolzovanie_CPP.html


Название: Re: Перекрытие виртуалов
Отправлено: OKTA от Апрель 16, 2014, 15:57
Да, спасибо.


Название: Re: Перекрытие виртуалов
Отправлено: Igors от Апрель 17, 2014, 07:52
Да, действительно, компиляторы gcc/icc выдают ошибку. Хотя using A::Test решает проблему, но как-то стремно (какую - ту или эту?)
Спасибо 


Название: Re: Перекрытие виртуалов [решено]
Отправлено: OKTA от Апрель 17, 2014, 09:28
Ту или эту это вы о каких?


Название: Re: Перекрытие виртуалов [решено]
Отправлено: Igors от Апрель 17, 2014, 10:27
Ту или эту это вы о каких?
О методах Test класса A, их 2. И какую открывает using (или обе) как-то не очень ясно.


Название: Re: Перекрытие виртуалов [решено]
Отправлено: OKTA от Апрель 17, 2014, 11:20
using A::Test всего лишь открывает видимость имени Test и компилятор будет знать, что "хорошо бы заглянуть и в родительский класс" при поиске Test.