Уважаемые коллеги, укажите, пожалуйста, где я тут не прав:---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---Заранее благодарен, всем кто ответит,
С.Г.
>Уважаемые коллеги, укажите, пожалуйста, где я тут не прав:
>
>---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() в производном классе у тебя переопределена, соответственно она должна вызываться у тебя без аргуметов.
>>Уважаемые коллеги, укажите, пожалуйста, где я тут не прав:
>>
>>---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(), которую я и собирался переопределять в производных классах. Что же получается, что, переопределив одну из функций, я теряю доступ к остальным функциям с таким же именем? В таком случае теряется смысл перегрузки (по крайней мере, при использовании ее в таком виде). Как выход, придется давать функциям разные имена. Или есть другое решение?С.Г.
>>>Уважаемые коллеги, укажите, пожалуйста, где я тут не прав:
>>>
>>>---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(), которую я и
>собирался переопределять в производных классах. Что же получается, что, переопределив одну
>из функций, я теряю доступ к остальным функциям с таким же
>именем? В таком случае теряется смысл перегрузки (по крайней мере, при
>использовании ее в таком виде). Как выход, придется давать функциям разные
>имена. Или есть другое решение?
>
>С.Г.
Если виртуальная функция не переопределяется в производном классе, то испоьзуется функция базового класса.
>>>Виртуальная функция 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).
С.Г.
>>>>Виртуальная функция 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);
>>>Уважаемые коллеги, укажите, пожалуйста, где я тут не прав:
>>>
>>>---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?
>
>С.Г.
> child c;
> c.base::test(5);Не так. Скорее
((Base&)c).test(5);
Однако уродливо. Есть более прямой способ, как я и описал выше.
1. Практически любому C++-программисту полезно почитать материалы из
C++ FAQ: http://new-brunswick.net/workshop/c++/faq/index.html.
По неведомым для меня причинам очень мало людей, осведомлённых даже
просто о существовании освещённых там тонкостей.2. Ваша проблема лечится добавлением в класс child строки
using base::test;
Всем спасибо! Так я и думал, что нужно дописать некоторую строчку (или как-то хитро вызывать метод), чтобы все стало на свои места.Также спасибо за ссылки (перед тем как постить сюда, я попытался найти ответ сам, но, увы...).
Еще раз всем спасибо!
С.Г.
>1. Практически любому C++-программисту полезно почитать материалы из
>C++ FAQ: http://new-brunswick.net/workshop/c++/faq/index.html.
>По неведомым для меня причинам очень мало людей, осведомлённых даже
>просто о существовании освещённых там тонкостей.
>
>2. Ваша проблема лечится добавлением в класс child строки
> using base::test;
Зачем? если можно вызвать виртуальную функцию через указатель? ;-)
как это сделать я описал выше. Помоему автору просто нужно купить книжку по С++ и хорошенько ее проштудировать.
Удачи!!!