URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 4526
[ Назад ]

Исходное сообщение
"C/C++ Перегрузка и наследование ??"

Отправлено С.Г. , 31-Июл-05 13:51 
Уважаемые коллеги, укажите, пожалуйста, где я тут не прав:

---tmp02.cpp---
class base {
public:
  virtual int test() { return 0; };
  virtual int test(int a) { test(); return 0; };
};

class child: public base {
public:
  int test() { return 1; };
};

int main(int argc, char *argv[]) {
  child c1;
  c1.test(1);
  return 0;
}

/* gcc-3.4.4
Компиляция tmp02.cpp (g++)
tmp02.cpp:15: error: no matching function for call to `child::test(int)'
tmp02.cpp:9: note: candidates are: virtual int child::test()
*** Завершено с кодом: 2 ***
*/
---tmp02.cpp---

С C/C++ я только знакомлюсь, до этого писал на Паскале,
и аналогичный код на нем работает:

---tmp02.pas---
program tmp02;
{$APPTYPE CONSOLE}
type
  TBase = class
    function Test(): Integer; overload; virtual;
    function Test(a: Integer): Integer; overload; virtual;
  end;
  TChild = class(TBase)
    function Test(): Integer; override;
  end;

function TBase.Test(): Integer; begin
  result := 0;
end;
function TBase.Test(a: Integer): Integer; begin
  result := Test();
end;
function TChild.Test(): Integer; begin
  result := 1;
end;

var
  C1: TChild;
begin
  C1 := TChild.Create();
  C1.Test(1);
end.
---tmp02.pas---

Заранее благодарен, всем кто ответит,
С.Г.


Содержание

Сообщения в этом обсуждении
"C/C++ Перегрузка и наследование ??"
Отправлено frenzy , 31-Июл-05 15:25 
>Уважаемые коллеги, укажите, пожалуйста, где я тут не прав:
>
>---tmp02.cpp---
>class base {
>public:
>  virtual int test() { return 0; };
>  virtual int test(int a) { test(); return 0; };
>};
>
>class child: public base {
>public:
>  int test() { return 1; };
>};
>
>int main(int argc, char *argv[]) {
>  child c1;
>  c1.test(1);
>  return 0;
>}
>
>/* gcc-3.4.4
>Компиляция tmp02.cpp (g++)
>tmp02.cpp:15: error: no matching function for call to `child::test(int)'
>tmp02.cpp:9: note: candidates are: virtual int child::test()
>*** Завершено с кодом: 2 ***
>*/
>---tmp02.cpp---
>
>С C/C++ я только знакомлюсь, до этого писал на Паскале,
>и аналогичный код на нем работает:
>
>---tmp02.pas---
>program tmp02;
>{$APPTYPE CONSOLE}
>type
>  TBase = class
>    function Test(): Integer; overload; virtual;
>    function Test(a: Integer): Integer; overload; virtual;
>  end;
>  TChild = class(TBase)
>    function Test(): Integer; override;
>  end;
>
>function TBase.Test(): Integer; begin
>  result := 0;
>end;
>function TBase.Test(a: Integer): Integer; begin
>  result := Test();
>end;
>function TChild.Test(): Integer; begin
>  result := 1;
>end;
>
>var
>  C1: TChild;
>begin
>  C1 := TChild.Create();
>  C1.Test(1);
>end.
>---tmp02.pas---
>
>Заранее благодарен, всем кто ответит,
>С.Г.

Виртуальная функция test() в производном классе у тебя переопределена, соответственно она должна вызываться у тебя без аргуметов.


"C/C++ Перегрузка и наследование ??"
Отправлено С.Г. , 31-Июл-05 16:04 
>>Уважаемые коллеги, укажите, пожалуйста, где я тут не прав:
>>
>>---tmp02.cpp---
>>class base {
>>public:
>>  virtual int test() { return 0; };
>>  virtual int test(int a) { test(); return 0; };
>>};
>>
>>class child: public base {
>>public:
>>  int test() { return 1; };
>>};
>>
>>int main(int argc, char *argv[]) {
>>  child c1;
>>  c1.test(1);
>>  return 0;
>>}
>>
>>/* gcc-3.4.4
>>Компиляция tmp02.cpp (g++)
>>tmp02.cpp:15: error: no matching function for call to `child::test(int)'
>>tmp02.cpp:9: note: candidates are: virtual int child::test()
>>*** Завершено с кодом: 2 ***
>>*/
>>---tmp02.cpp---
>
>Виртуальная функция test() в производном классе у тебя переопределена, соответственно она должна
>вызываться у тебя без аргуметов.


В том-то и дело, что я переопределяю только одну из двух виртуальных функций с одинаковым названием (а именно test()), но с различным числом параметров, что должно трактоваться как две разных функции (если я ничего не путаю). Соотв.  я ожидал, что функция test(int a) достанется в наследство от base, в которой вызывается test(), которую я и собирался переопределять в производных классах. Что же получается, что, переопределив одну из функций, я теряю доступ к остальным функциям с таким же именем? В таком случае теряется смысл перегрузки (по крайней мере, при использовании ее в таком виде). Как выход, придется давать функциям разные имена. Или есть другое решение?

С.Г.


"C/C++ Перегрузка и наследование ??"
Отправлено frenzy , 31-Июл-05 16:34 
>>>Уважаемые коллеги, укажите, пожалуйста, где я тут не прав:
>>>
>>>---tmp02.cpp---
>>>class base {
>>>public:
>>>  virtual int test() { return 0; };
>>>  virtual int test(int a) { test(); return 0; };
>>>};
>>>
>>>class child: public base {
>>>public:
>>>  int test() { return 1; };
>>>};
>>>
>>>int main(int argc, char *argv[]) {
>>>  child c1;
>>>  c1.test(1);
>>>  return 0;
>>>}
>>>
>>>/* gcc-3.4.4
>>>Компиляция tmp02.cpp (g++)
>>>tmp02.cpp:15: error: no matching function for call to `child::test(int)'
>>>tmp02.cpp:9: note: candidates are: virtual int child::test()
>>>*** Завершено с кодом: 2 ***
>>>*/
>>>---tmp02.cpp---
>>
>>Виртуальная функция test() в производном классе у тебя переопределена, соответственно она должна
>>вызываться у тебя без аргуметов.
>
>
>В том-то и дело, что я переопределяю только одну из двух виртуальных
>функций с одинаковым названием (а именно test()), но с различным числом
>параметров, что должно трактоваться как две разных функции (если я ничего
>не путаю). Соотв.  я ожидал, что функция test(int a) достанется
>в наследство от base, в которой вызывается test(), которую я и
>собирался переопределять в производных классах. Что же получается, что, переопределив одну
>из функций, я теряю доступ к остальным функциям с таким же
>именем? В таком случае теряется смысл перегрузки (по крайней мере, при
>использовании ее в таком виде). Как выход, придется давать функциям разные
>имена. Или есть другое решение?
>
>С.Г.
Если виртуальная функция не переопределяется в производном классе, то испоьзуется функция базового класса.


"C/C++ Перегрузка и наследование ??"
Отправлено С.Г. , 31-Июл-05 17:12 
>>>Виртуальная функция test() в производном классе у тебя переопределена, >соответственно она должна
>>>вызываться у тебя без аргуметов.
>>
>>
>>В том-то и дело, что я переопределяю только одну из двух виртуальных
>>функций с одинаковым названием (а именно test()), но с различным числом
>>параметров, что должно трактоваться как две разных функции (если я ничего
>>не путаю). Соотв.  я ожидал, что функция test(int a) достанется
>>в наследство от base, в которой вызывается test(), которую я и
>>собирался переопределять в производных классах. Что же получается, что, >переопределив одну
>>из функций, я теряю доступ к остальным функциям с таким же
>>именем? В таком случае теряется смысл перегрузки (по крайней мере, при
>>использовании ее в таком виде). Как выход, придется давать функциям разные
>>имена. Или есть другое решение?
>>
>>С.Г.
>
>Если виртуальная функция не переопределяется в производном классе, то испоьзуется >функция базового класса.
>

Вот я на это и надеялся. Тогда что от меня требует компилер?? :

tmp02.cpp:15: error: no matching function for call to `child::test(int)'
tmp02.cpp:9: note: candidates are: virtual int child::test()

Т.е. после переопределения в дочернем классе функции test() компилер как бы не замечает, что в базовом классе помимо test() есть еще и test(int a).

С.Г.


"C/C++ Перегрузка и наследование ??"
Отправлено frenzy , 31-Июл-05 17:21 
>>>>Виртуальная функция test() в производном классе у тебя переопределена, >соответственно она должна
>>>>вызываться у тебя без аргуметов.
>>>
>>>
>>>В том-то и дело, что я переопределяю только одну из двух виртуальных
>>>функций с одинаковым названием (а именно test()), но с различным числом
>>>параметров, что должно трактоваться как две разных функции (если я ничего
>>>не путаю). Соотв.  я ожидал, что функция test(int a) достанется
>>>в наследство от base, в которой вызывается test(), которую я и
>>>собирался переопределять в производных классах. Что же получается, что, >переопределив одну
>>>из функций, я теряю доступ к остальным функциям с таким же
>>>именем? В таком случае теряется смысл перегрузки (по крайней мере, при
>>>использовании ее в таком виде). Как выход, придется давать функциям разные
>>>имена. Или есть другое решение?
>>>
>>>С.Г.
>>
>>Если виртуальная функция не переопределяется в производном классе, то испоьзуется >функция базового класса.
>>
>
>Вот я на это и надеялся. Тогда что от меня требует компилер??
>:
>
>tmp02.cpp:15: error: no matching function for call to `child::test(int)'
>tmp02.cpp:9: note: candidates are: virtual int child::test()
>
>Т.е. после переопределения в дочернем классе функции test() компилер как бы не
>замечает, что в базовом классе помимо test() есть еще и test(int
>a).
>
>С.Г.

Вызывать нужно вот так:
base *p;child c1;
p = &c1;p->test(1);


"C/C++ Перегрузка и наследование ??"
Отправлено elvenic , 31-Июл-05 17:26 
>>>Уважаемые коллеги, укажите, пожалуйста, где я тут не прав:
>>>
>>>---tmp02.cpp---
>>>class base {
>>>public:
>>>  virtual int test() { return 0; };
>>>  virtual int test(int a) { test(); return 0; };
>>>};
>>>
>>>class child: public base {
>>>public:
>>>  int test() { return 1; };
>>>};
>>>
>>>int main(int argc, char *argv[]) {
>>>  child c1;
>>>  c1.test(1);
>>>  return 0;
>>>}
>>>
>>>/* gcc-3.4.4
>>>Компиляция tmp02.cpp (g++)
>>>tmp02.cpp:15: error: no matching function for call to `child::test(int)'
>>>tmp02.cpp:9: note: candidates are: virtual int child::test()
>>>*** Завершено с кодом: 2 ***
>>>*/
>>>---tmp02.cpp---
>>
>>Виртуальная функция test() в производном классе у тебя переопределена, соответственно она должна
>>вызываться у тебя без аргуметов.
>
>
>В том-то и дело, что я переопределяю только одну из двух виртуальных
>функций с одинаковым названием (а именно test()), но с различным числом
>параметров, что должно трактоваться как две разных функции (если я ничего
>не путаю). Соотв.  я ожидал, что функция test(int a) достанется
>в наследство от base, в которой вызывается test(), которую я и
>собирался переопределять в производных классах. Что же получается, что, переопределив одну
>из функций, я теряю доступ к остальным функциям с таким же
>именем?

(sorry for writing in english, have not been using cyrillic keyboard for several years, forgot layout ;)

That's exactly what happens.

See, for example:

http://cpptips.hyperformix.com/cpptips/virt_name_hide

As you can see, that was a confusing topic even in 1991 ;)

According to the C++ rules, a name defined in the derived class (in your case, child::test), not overrides, but _hides_ the name from the base class - it means that all methods, data members (perhaps even enum members and embedded classes?) with the same name are not visible in the derived class - the method signature - test() or test(int) - is not taken into account here.


В таком случае теряется смысл перегрузки (по крайней мере, при
>использовании ее в таком виде). Как выход, придется давать функциям разные
>имена. Или есть другое решение?

I'm not sure right away, and am too lazy to test, but something like:

    child c;
    c.base::test(5);

might work - try it?

>
>С.Г.



"C/C++ Перегрузка и наследование ??"
Отправлено DeadMustdie , 31-Июл-05 17:28 
>    child c;
>    c.base::test(5);

Не так. Скорее
   ((Base&)c).test(5);
Однако уродливо. Есть более прямой способ, как я и описал выше.


"C/C++ Перегрузка и наследование ??"
Отправлено DeadMustdie , 31-Июл-05 17:26 
1. Практически любому C++-программисту полезно почитать материалы из
C++ FAQ: http://new-brunswick.net/workshop/c++/faq/index.html.
По неведомым для меня причинам очень мало людей, осведомлённых даже
просто о существовании освещённых там тонкостей.

2. Ваша проблема лечится добавлением в класс child строки
  using base::test;


"C/C++ Перегрузка и наследование ??"
Отправлено С.Г. , 31-Июл-05 17:40 
Всем спасибо! Так я и думал, что нужно дописать некоторую строчку (или как-то хитро вызывать метод), чтобы все стало на свои места.

Также спасибо за ссылки (перед тем как постить сюда, я попытался найти ответ сам, но, увы...).

Еще раз всем спасибо!
С.Г.


"C/C++ Перегрузка и наследование ??"
Отправлено frenzy , 31-Июл-05 17:45 
>1. Практически любому C++-программисту полезно почитать материалы из
>C++ FAQ: http://new-brunswick.net/workshop/c++/faq/index.html.
>По неведомым для меня причинам очень мало людей, осведомлённых даже
>просто о существовании освещённых там тонкостей.
>
>2. Ваша проблема лечится добавлением в класс child строки
>  using base::test;
Зачем? если можно вызвать виртуальную функцию через указатель? ;-)
как это сделать я описал выше. Помоему автору просто нужно купить книжку по С++ и хорошенько ее проштудировать.
Удачи!!!