class A
{
public:
void func()
{
cout << "A\n";
}
};
class B : public A
{
public:
boolfunc() // ИСПРАВЛЕНИЕ №1. Если заменить на void func(), то все нормально
{
cout << "B\n";
return true;
}
void ssss()
{
B::func(); // С2668
}
protected:
using A::func;// ИСПРАВЛЕНИЕ №2. Закаментировать и все заработает
};
Л>class A
Л>{
Л>public:
Л> void func()
Л> {
Л> cout << "A\n";
Л> }
Л>};
Л>class B : public A
Л>{
Л>public:
Л> boolfunc() // ИСПРАВЛЕНИЕ №1. Если заменить на void func(), то все нормально
Л>protected:
Л> using A::func;// ИСПРАВЛЕНИЕ №2. Закаментировать и все заработает
Л>};
Л>
Л>А если сделать исправление №2, то работает??
В первом случае — потому что перегруженные функции не могут отличаться только типом возвращаемого значения.
Во втором — потому что без using функция B::g скрывает, а не перегружает A::b.
А подтверждение слов — цитаты из Писания:
— Function declarations that differ only in the return type cannot be overloaded.
(13.1.2)
A function member of a derived class is not in the same
scope as a function member of the same name in a base class. [Example:
class B {
public:
int f(int);
};
class D : public B {
public:
int f(char*);
};
Here D::f(char*) hides B::f(int) rather than overloading it.
Здравствуйте, Константин Л., Вы писали:
КЛ>тк твои методы отличаются только возвращаемым значением. КЛ>если не ошибаюсь, то это может помочь компилятору для опред, какой метод нужно вызвать КЛ>
КЛ>B b;
КЛ>bool value = b.f();
КЛ>
Мне казалось, что retval никогда не используется при определение того какая перегруженная функция должна быть вызвана
Здравствуйте, LuciferMoscow, Вы писали:
LM>Здравствуйте, Константин Л., Вы писали:
КЛ>>тк твои методы отличаются только возвращаемым значением. КЛ>>если не ошибаюсь, то это может помочь компилятору для опред, какой метод нужно вызвать КЛ>>
КЛ>>B b;
КЛ>>bool value = b.f();
КЛ>>
LM>Мне казалось, что retval никогда не используется при определение того какая перегруженная функция должна быть вызвана
Здравствуйте, Константин Л., Вы писали: LM>>Мне казалось, что retval никогда не используется при определение того какая перегруженная функция должна быть вызвана
КЛ>хз
Здравствуйте, LuciferMoscow, Вы писали:
LM>Здравствуйте, Константин Л., Вы писали:
КЛ>>тк твои методы отличаются только возвращаемым значением. КЛ>>если не ошибаюсь, то это может помочь компилятору для опред, какой метод нужно вызвать КЛ>>
КЛ>>B b;
КЛ>>bool value = b.f();
КЛ>>
LM>Мне казалось, что retval никогда не используется при определение того какая перегруженная функция должна быть вызвана
Иногда это можно делать, и протестов не будет...
Посмотрите сюда:
//Листинг 9.6. Наследование от абстрактного классаclass Food // абстрактный класс "Пища животного"
{ public:
virtual string typeFood() const = 0; // тип пищи
};
class Animal // абстрактный класс "Животное"
{ public:
virtual string kind() const = 0; // вид животногоvirtual Food& eats() = 0; // что ест
};
class Tiger: public Animal // Тигр – конкретный вид животного
{ public:
virtual string kind() const// идентификация вида
{ return"Tiger"; }
class TigerFood: public Food // пища тигра
{ public:
virtual string typeFood() const// идентификация пищи тигра
{ return"Tiger food"; }
};
virtual TigerFood& eats() // ест пищу тигра
{ return tiger; }
private:
TigerFood tiger; // объект – пища тигра
};
class Dog: public Animal // Собака – конкретный вид животного
{ public:
virtual string kind() const// идентификация вида
{ return"Dog"; }
class DogFood: public Food // пища собаки
{ public:
virtual string typeFood() const// идентификация пищи собаки
{ return"Dog food"; }
};
virtual DogFood& eats() // ест пищу собаки
{ return dog;
}
private:
DogFood dog; // объект – пища собаки
};
int main()
{ Tiger t; Dog d; // объекты-животные
Animal& pt = t; Animal& pd = d; // подстановка ссылок
Animal *p[] = { &t, &d }; // подстановка указателей
// виртуальный вызов по ссылке
cout << pt.eats().typeFood() << endl;
cout << pd.eats().typeFood() << endl;
// виртуальный вызов по указателю
cout << p[0]->eats().typeFood() << endl;
cout << p[1]->eats().typeFood() << endl;
// присвоение измененного типа
Tiger::TigerFood tf = t.eats();
Dog::DogFood df = d.eats();
return 0;
}
Сначала определены два абстрактных базовых класса Food и Animal. Эти классы определяют для своих наследников минимальные общие интерфейсы (чистые виртуальные функции). Класс Tiger, наследуя от Animal, содержит вложенный класс TigerFood — наследника от Food. Класс TigerFood вложен в Tiger, так как эти классы тесно связаны — тигр есть только свою пищу. Впрочем, исходный абстрактный базовый класс Food можно вложить и в исходный абстрактный класс Animal:
Тогда вложенный класс TigerFood будет наследником от вложенного абстрактного класса Food.
Метод eats(), который в базовом классе Animal возвращал ссылку на базовый класс Food, переопределен и возвращает ссылку на TigerFood — изменено возвращаемое значение. Аналогично можно изменять и тип возвращаемого указателя.
Точно такое строение имеет и класс Dog. Главная программа демонстрирует правильные вызовы виртуальных функций eats() через ссылки и указатели базового типа.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
V>В первом случае — потому что перегруженные функции не могут отличаться только типом возвращаемого значения. V>Во втором — потому что без using функция B::g скрывает, а не перегружает A::b.
Подожди. Если заменяем bool на void и есть using объявление, это что, уже не перегрузка (с нарушением), а с bool все же перегрузка?
V>А подтверждение слов — цитаты из Писания: V>
V>— Function declarations that differ only in the return type cannot be overloaded.
V>(13.1.2)
В Писании есть также такое:
7.3.3/12
When a using-declaration brings names from a base class into a derived class scope, member functions in
the derived class override and/or hide member functions with the same name and parameter types in a base
class (rather than conflicting).
Так что, имхо, баг компилятора это.
Of course, the code must be complete enough to compile and link.
вот тут то мы и получаем "перегрузку", но тк это не перегрузка из-за различия только в возвр. значении получаем ошибку. Причем ошибка будет вне зависимотси от того, что возвр. func — void или bool
КЛ>вот тут то мы и получаем "перегрузку", но тк это не перегрузка из-за различия только в возвр. значении получаем ошибку.
Странная логика. Где же ты получил ошибку? Разве компилятор сказал тебе, что функции нельзя перегрузить, потому как они отличаются только типом возвращаемого значения? Нет, не сказал такого. Позволил "перегрузить".
КЛ>Причем ошибка будет вне зависимотси от того, что возвр. func — void или bool
Как раз с типом void вижуал перестает колбасить (или его сколбашивает по другому) и он компилит программу без ошибок.
На самом деле все проще. В случае using объявлений членов классов предпочтение отдается члену производного класса (я уже цитировал пункт 7.3.3/12).
Of course, the code must be complete enough to compile and link.
Здравствуйте, Lorenzo_LAMAS, Вы писали:
КЛ>>вот тут то мы и получаем "перегрузку", но тк это не перегрузка из-за различия только в возвр. значении получаем ошибку.
L_L>Странная логика. Где же ты получил ошибку? Разве компилятор сказал тебе, что функции нельзя перегрузить, потому как они отличаются только типом возвращаемого значения? Нет, не сказал такого. Позволил "перегрузить".
КЛ>>Причем ошибка будет вне зависимотси от того, что возвр. func — void или bool
L_L>Как раз с типом void вижуал перестает колбасить (или его сколбашивает по другому) и он компилит программу без ошибок.
L_L>На самом деле все проще. В случае using объявлений членов классов предпочтение отдается члену производного класса (я уже цитировал пункт 7.3.3/12).
я это вообще не компилил, а предположил, как должно быть
Здравствуйте, Lorenzo_LAMAS, Вы писали:
КЛ>>вот тут то мы и получаем "перегрузку", но тк это не перегрузка из-за различия только в возвр. значении получаем ошибку.
L_L>Странная логика. Где же ты получил ошибку? Разве компилятор сказал тебе, что функции нельзя перегрузить, потому как они отличаются только типом возвращаемого значения? Нет, не сказал такого. Позволил "перегрузить".
КЛ>>Причем ошибка будет вне зависимотси от того, что возвр. func — void или bool
L_L>Как раз с типом void вижуал перестает колбасить (или его сколбашивает по другому) и он компилит программу без ошибок.
L_L>На самом деле все проще. В случае using объявлений членов классов предпочтение отдается члену производного класса (я уже цитировал пункт 7.3.3/12).
ок, тогда в тех двух случаях, которые я описал, должно все компилиться без проблем. Значит баг компилера
Познавательно в некоем роде
Только к чему это все ? В вопросе перекрыт невиртуальный метод, объявление в классе-наследнике скрывает объявление одноименного метода в базовом классе. _Никакого_ отношения ваш пример к этому не имеет.
Здравствуйте, LaptevVV, Вы писали: КЛ>>>тк твои методы отличаются только возвращаемым значением. КЛ>>>если не ошибаюсь, то это может помочь компилятору для опред, какой метод нужно вызвать КЛ>>>
КЛ>>>B b;
КЛ>>>bool value = b.f();
КЛ>>>
LM>>Мне казалось, что retval никогда не используется при определение того какая перегруженная функция должна быть вызвана LVV>Иногда это можно делать, и протестов не будет... LVV>Посмотрите сюда:
<skipped>
Я не о том. То, что производный класс может "уточнить" возвращаемое значение я знаю.
Я имел ввиду следующее:
// declarationsclass A;
class B;// эти два класса не связаны наследованием
A f(int,float);
B f(float,int);
// using
A a=f(1,1);
С моей точки зрения в данномм коде есть неоднозначность(для компилятора, какую функцию вызывать), которую можно разрешить посмотрев на возвращаемоле значение, но никакой компилятор(читающий стандарт) этого делать не будет
После более внимательного рассмотрения выяснилось, что возможно и баг, поскольку интел и комо этот код съедают и 7.3.3/12 тоже это подтверждает. Тем не менее, того что я написал это не отменяет. Поэтому теперь уже не знаю как правильно
Здравствуйте, LaptevVV, Вы писали:
LVV>Сначала определены два абстрактных базовых класса Food и Animal. Эти классы определяют для своих наследников минимальные общие интерфейсы (чистые виртуальные функции). Класс Tiger, наследуя от Animal, содержит вложенный класс TigerFood — наследника от Food. Класс TigerFood вложен в Tiger, так как эти классы тесно связаны — тигр есть только свою пищу. Впрочем, исходный абстрактный базовый класс Food можно вложить и в исходный абстрактный класс Animal:
Знаете это наверно оффтопик, но скажу — надо вкладывать наоборот Animal в Food, так как на этом построена сама природа — Animal другому Animal'у может быть Food )))))
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]