The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]




Версия для распечатки Пред. тема | След. тема
Новые ответы [ Отслеживать ]
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, 15:25 , 31-Июл-05 (1)
    >Уважаемые коллеги, укажите, пожалуйста, где я тут не прав:
    >
    >---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++ Перегрузка и наследование ??, !*! С.Г., 16:04 , 31-Июл-05 (2)
      >>Уважаемые коллеги, укажите, пожалуйста, где я тут не прав:
      >>
      >>---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, 16:34 , 31-Июл-05 (3)
        >>>Уважаемые коллеги, укажите, пожалуйста, где я тут не прав:
        >>>
        >>>---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++ Перегрузка и наследование ??, !*! С.Г., 17:12 , 31-Июл-05 (4)
          >>>Виртуальная функция 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, 17:21 , 31-Июл-05 (5)
            >>>>Виртуальная функция 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, 17:26 , 31-Июл-05 (7)
        >>>Уважаемые коллеги, укажите, пожалуйста, где я тут не прав:
        >>>
        >>>---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, 17:26 , 31-Июл-05 (6)
    1. Практически любому C++-программисту полезно почитать материалы из
    C++ FAQ: http://new-brunswick.net/workshop/c++/faq/index.html.
    По неведомым для меня причинам очень мало людей, осведомлённых даже
    просто о существовании освещённых там тонкостей.

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

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

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

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

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



Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру