Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C++ Builder > [C++ Warning] W8022 hides virtual function


Автор: ZVano 9.2.2011, 12:25
Есть классы
Код

class Base{
public:
  virtual void func(type1 p);
}

class Derived :public Base{
public:
  void func(type2 p);
}



Компилятор пишет Warning
[C++ Warning] : W8022 'Derived::func(type2 p)' hides virtual function 'Base::func(type1 p)'

Что переводится как "Derived::func(type2 p) #потомок#  скрывает виртуальную функцию Base::func(type1 p) #родитель# "
Ну это и так понятно, мы же явно сказали в базовом классе, что метод "func" виртуальный, значит подразумевается что в потомках он будет переопределен.
Зачем тогда этот варнинг? Или я чего то недопонимаю в концепции ООП?

Мне нужно определить в предке виртуальный метод, который будет переопределен в потомках.
При этом я хочу не просто заменить метод, а сделать так, чтобы метод родителя автоматически вызывался после вызова метода потомка.
Если я делаю\понимаю что-то неверно, ткните носом.
Если все делаю верно, скажите как убрать этот варнинг.

Добавлено:
Идем на сайт CodeGear http://docwiki.embarcadero.com/RADStudio/en/W8022_'function1'_hides_virtual_function_'function2'_(C%2B%2B)
и видим
Код

W8022 'function1' hides virtual function 'function2' (C++)
Go Up to Compiler Errors And Warnings (C++) Index 
(Command-line option to suppress warning: -w-hid) 

A virtual function in a base class is usually overridden by a declaration in a derived class. 
In this case, a declaration with the same name but different argument types makes the virtual functions inaccessible to further derived classes.


что переводится как:
Код

Виртуальная функции, объявленая в родительском классе, как правило, переопределяется в дочернем классе.
В этом случае объявление в дочернем классе функции с тем же именем, но другими типами аргументов, делают недоступными виртуальную функцию в потомках.


Т.е. в моем случае "class Derived" имеет доступ к виртуальной функции "class Base", но для потомков "class Derived"  эта функция будет недоступна. 
Вместо начальной виртуальной функции "Base::func(type1 p)" будет вызываться "Derived::func(type2 p)"

Верно ли я понял?

Автор: Dem_max 9.2.2011, 16:58
Цитата

Вместо начальной виртуальной функции "Base::func(type1 p)" будет вызываться "Derived::func(type2 p)"

все верно, у тебя же в базовом классе отсутствует функция func(type1 p), поэтому будет вызвана func(type2 p)

Автор: ZVano 9.2.2011, 18:42
Цитата(Dem_max @  9.2.2011,  16:58 Найти цитируемый пост)
все верно, у тебя же в базовом классе отсутствует функция func(type1 p), поэтому будет вызвана func(type2 p)

Спасибо. 

Теперь буду думать чем это может аукнуться в моем проекте, и как исправлять косяк :(

Автор: Dem_max 9.2.2011, 19:08
такая фигня особо часто встречается если работать с GDI+

Автор: xvr 10.2.2011, 13:53
Цитата(ZVano @  9.2.2011,  12:25 Найти цитируемый пост)
Ну это и так понятно, мы же явно сказали в базовом классе, что метод "func" виртуальный, значит подразумевается что в потомках он будет переопределен.

В данном случае вы его не переопределили. Derived::func не является версией Base::func - это 2 разные функции, и в экземпляре класса Derived вы сможете позвать обе (правда для вызова версии из Base придется дописать пару букв  smile )
Цитата

Или я чего то недопонимаю в концепции ООП?
Угу.
Код

class Base{
public:
  virtual void func(type1 p);
};
class Derived :public Base{
public:
  void func(type2 p);
};

Base* p=new Derived;
p->func(some); // вызовется Base::func
А если сделать так:
Код

class Base{
public:
  virtual void func(type1 p);
};
class Derived :public Base{
public:
  void func( type1 p);
};

Base* p=new Derived;
p->func(some); // вызовется Derived::func


Цитата

Мне нужно определить в предке виртуальный метод, который будет переопределен в потомках.
При этом я хочу не просто заменить метод, а сделать так, чтобы метод родителя автоматически вызывался после вызова метода потомка.


Код

class Base {

 virtual void call_my_method() =0;

public:

 void my_method()
  {
    call_my_method();
    some_extra_actions() ...
  }
};

В потомках переопределять call_my_method, а вызывать my_method

Автор: borisbn 10.2.2011, 14:58
ZVano, и ещё учти, что в зависимости от того, наследован ли твой Base от TObject (или любого его потомка), в его конструкторе вызов виртуальных функций ведёт себя по-разному. В VCL конструктор класса, наследованного от TObject фактически конструктором не является, а это - просто функция. Можешь проверить

Код

class Base //: public TObject // <---- разкомментируй это наследование
{
public:
    Base() {
        foo(); // вообще-то в Си++ это - ошибка, и, если не наследоваться от TObject, то она и всплывёт
    }
    virtual void foo() = 0;
};

class Deriv : public Base
{
public:
    Deriv() {}
    virtual void foo() {
        ShowMessage( "Deriv::foo()" );
    }
};


Deriv * d = new Deriv();

Автор: ZVano 18.2.2011, 13:44
Спасибо всем, разобрался.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)