error C2668: 'A::func' : ambiguous call
От: Лекс Россия  
Дата: 19.09.06 15:42
Оценка:
Всем привет.

Почему это не работает?

class A
{
public:
    void func()
    {
        cout << "A\n";
    }
};

class B : public A
{
public:
    bool func()         // ИСПРАВЛЕНИЕ №1. Если заменить на void func(), то все нормально
    {
        cout << "B\n";
        return true;
    }

    void ssss()
    {
        B::func();    // С2668
    }

protected:
    using A::func;      // ИСПРАВЛЕНИЕ №2. Закаментировать и все заработает 
};



А если сделать исправление №2, то работает??
C Уважением,
Андрей.
Re: error C2668: 'A::func' : ambiguous call
От: Константин Л. Франция  
Дата: 19.09.06 16:03
Оценка:
Здравствуйте, Лекс, Вы писали:

Л>Всем привет.


Л>Почему это не работает?


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



B b;
bool value = b.f();
Re: error C2668: 'A::func' : ambiguous call
От: vvotan Россия  
Дата: 19.09.06 17:15
Оценка: +1
Здравствуйте, Лекс, Вы писали:


Л>
Л>class A
Л>{
Л>public:
Л>    void func()
Л>    {
Л>        cout << "A\n";
Л>    }
Л>};

Л>class B : public A
Л>{
Л>public:
Л>    bool func()         // ИСПРАВЛЕНИЕ №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.

(13.2.1)
--
Sergey Chadov

... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: error C2668: 'A::func' : ambiguous call
От: Lorenzo_LAMAS  
Дата: 20.09.06 07:51
Оценка:
Баг компилятора.
Of course, the code must be complete enough to compile and link.
Re[2]: error C2668: 'A::func' : ambiguous call
От: LuciferMoscow Россия  
Дата: 20.09.06 08:21
Оценка:
Здравствуйте, Константин Л., Вы писали:

КЛ>тк твои методы отличаются только возвращаемым значением.

КЛ>если не ошибаюсь, то это может помочь компилятору для опред, какой метод нужно вызвать
КЛ>
КЛ>B b;
КЛ>bool value = b.f();
КЛ>

Мне казалось, что retval никогда не используется при определение того какая перегруженная функция должна быть вызвана
Re[3]: error C2668: 'A::func' : ambiguous call
От: Константин Л. Франция  
Дата: 20.09.06 08:30
Оценка:
Здравствуйте, LuciferMoscow, Вы писали:

LM>Здравствуйте, Константин Л., Вы писали:


КЛ>>тк твои методы отличаются только возвращаемым значением.

КЛ>>если не ошибаюсь, то это может помочь компилятору для опред, какой метод нужно вызвать
КЛ>>
КЛ>>B b;
КЛ>>bool value = b.f();
КЛ>>

LM>Мне казалось, что retval никогда не используется при определение того какая перегруженная функция должна быть вызвана

хз
Re[4]: error C2668: 'A::func' : ambiguous call
От: Bell Россия  
Дата: 20.09.06 08:40
Оценка:
Здравствуйте, Константин Л., Вы писали:
LM>>Мне казалось, что retval никогда не используется при определение того какая перегруженная функция должна быть вызвана

КЛ>хз


Именно так и есть — смотри пост vvotan
Любите книгу — источник знаний (с) М.Горький
Re[3]: error C2668: 'A::func' : ambiguous call
От: LaptevVV Россия  
Дата: 20.09.06 08:45
Оценка: +1 -1
Здравствуйте, 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:
class Animal
{ public: 
    class Food                // вложенный абстрактный класс
    { public: 
        virtual string typeFood() const = 0;
    };
    virtual string kind() const = 0;
    virtual Food& eats() = 0;
};

Тогда вложенный класс TigerFood будет наследником от вложенного абстрактного класса Food.
Метод eats(), который в базовом классе Animal возвращал ссылку на базовый класс Food, переопределен и возвращает ссылку на TigerFood — изменено возвращаемое значение. Аналогично можно изменять и тип возвращаемого указателя.
Точно такое строение имеет и класс Dog. Главная программа демонстрирует правильные вызовы виртуальных функций eats() через ссылки и указатели базового типа.

Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[2]: error C2668: 'A::func' : ambiguous call
От: Lorenzo_LAMAS  
Дата: 20.09.06 09:04
Оценка:
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.
Re: error C2668: 'A::func' : ambiguous call
От: Константин Л. Франция  
Дата: 20.09.06 09:23
Оценка:
Здравствуйте, Лекс, Вы писали:

Л>Всем привет.


Л>Почему это не работает?


стоп. давай попонятнее

1)

Л>
Л>class A
Л>{
Л>public:
Л>    void func()
Л>    {
Л>        cout << "A\n";
Л>    }
Л>};

Л>class B : public A
Л>{
Л>public:
Л>    bool func()
Л>    {
Л>        cout << "B\n";
Л>        return true;
Л>    }

Л>    void ssss()
Л>    {
Л>        B::func();    // С2668
Л>    }
Л>


тут все должно работать, тк B::func скрывает имя A::func. Причем это будет вне зависимости от типов аргументов и возвр. значения.


2)

Л>
Л>class A
Л>{
Л>public:
Л>    void func()
Л>    {
Л>        cout << "A\n";
Л>    }
Л>};

Л>class B : public A
Л>{
Л>public:
Л>    bool func()
Л>    {
Л>        cout << "B\n";
Л>        return true;
Л>    }

Л>    void ssss()
Л>    {
Л>        B::func();
Л>    }

Л>protected:
Л>    using A::func;
Л>};
Л>


вот тут то мы и получаем "перегрузку", но тк это не перегрузка из-за различия только в возвр. значении получаем ошибку. Причем ошибка будет вне зависимотси от того, что возвр. func — void или bool
Re[2]: error C2668: 'A::func' : ambiguous call
От: Lorenzo_LAMAS  
Дата: 20.09.06 09:42
Оценка: 1 (1)
КЛ>вот тут то мы и получаем "перегрузку", но тк это не перегрузка из-за различия только в возвр. значении получаем ошибку.

Странная логика. Где же ты получил ошибку? Разве компилятор сказал тебе, что функции нельзя перегрузить, потому как они отличаются только типом возвращаемого значения? Нет, не сказал такого. Позволил "перегрузить".

КЛ>Причем ошибка будет вне зависимотси от того, что возвр. func — void или bool


Как раз с типом void вижуал перестает колбасить (или его сколбашивает по другому) и он компилит программу без ошибок.

На самом деле все проще. В случае using объявлений членов классов предпочтение отдается члену производного класса (я уже цитировал пункт 7.3.3/12).
Of course, the code must be complete enough to compile and link.
Re[3]: error C2668: 'A::func' : ambiguous call
От: Константин Л. Франция  
Дата: 20.09.06 10:29
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

КЛ>>вот тут то мы и получаем "перегрузку", но тк это не перегрузка из-за различия только в возвр. значении получаем ошибку.


L_L>Странная логика. Где же ты получил ошибку? Разве компилятор сказал тебе, что функции нельзя перегрузить, потому как они отличаются только типом возвращаемого значения? Нет, не сказал такого. Позволил "перегрузить".


КЛ>>Причем ошибка будет вне зависимотси от того, что возвр. func — void или bool


L_L>Как раз с типом void вижуал перестает колбасить (или его сколбашивает по другому) и он компилит программу без ошибок.


L_L>На самом деле все проще. В случае using объявлений членов классов предпочтение отдается члену производного класса (я уже цитировал пункт 7.3.3/12).


я это вообще не компилил, а предположил, как должно быть
Re[3]: error C2668: 'A::func' : ambiguous call
От: Константин Л. Франция  
Дата: 20.09.06 11:00
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

КЛ>>вот тут то мы и получаем "перегрузку", но тк это не перегрузка из-за различия только в возвр. значении получаем ошибку.


L_L>Странная логика. Где же ты получил ошибку? Разве компилятор сказал тебе, что функции нельзя перегрузить, потому как они отличаются только типом возвращаемого значения? Нет, не сказал такого. Позволил "перегрузить".


КЛ>>Причем ошибка будет вне зависимотси от того, что возвр. func — void или bool


L_L>Как раз с типом void вижуал перестает колбасить (или его сколбашивает по другому) и он компилит программу без ошибок.


L_L>На самом деле все проще. В случае using объявлений членов классов предпочтение отдается члену производного класса (я уже цитировал пункт 7.3.3/12).


ок, тогда в тех двух случаях, которые я описал, должно все компилиться без проблем. Значит баг компилера
Re[4]: error C2668: 'A::func' : ambiguous call
От: Lorenzo_LAMAS  
Дата: 20.09.06 11:09
Оценка:
КЛ>ок, тогда в тех двух случаях, которые я описал, должно все компилиться без проблем. Значит баг компилера

Да, например у g++ проблем с таким кодом нет.
Of course, the code must be complete enough to compile and link.
Re[4]: error C2668: 'A::func' : ambiguous call
От: SexMachine Украина www.is.svitonline.com/sashko1
Дата: 20.09.06 15:42
Оценка:
Здравствуйте, LaptevVV,

Познавательно в некоем роде
Только к чему это все ? В вопросе перекрыт невиртуальный метод, объявление в классе-наследнике скрывает объявление одноименного метода в базовом классе. _Никакого_ отношения ваш пример к этому не имеет.
У кого-то варит голова, у кого-то — желудок...
Re[4]: error C2668: 'A::func' : ambiguous call
От: LuciferMoscow Россия  
Дата: 20.09.06 15:46
Оценка:
Здравствуйте, LaptevVV, Вы писали:
КЛ>>>тк твои методы отличаются только возвращаемым значением.
КЛ>>>если не ошибаюсь, то это может помочь компилятору для опред, какой метод нужно вызвать
КЛ>>>
КЛ>>>B b;
КЛ>>>bool value = b.f();
КЛ>>>

LM>>Мне казалось, что retval никогда не используется при определение того какая перегруженная функция должна быть вызвана
LVV>Иногда это можно делать, и протестов не будет...
LVV>Посмотрите сюда:
<skipped>
Я не о том. То, что производный класс может "уточнить" возвращаемое значение я знаю.
Я имел ввиду следующее:
// declarations
class A;
class B;// эти два класса не связаны наследованием
A f(int,float);
B f(float,int);

// using
A a=f(1,1);

С моей точки зрения в данномм коде есть неоднозначность(для компилятора, какую функцию вызывать), которую можно разрешить посмотрев на возвращаемоле значение, но никакой компилятор(читающий стандарт) этого делать не будет
Re[3]: error C2668: 'A::func' : ambiguous call
От: vvotan Россия  
Дата: 20.09.06 15:55
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:


L_L>Так что, имхо, баг компилятора это.


После более внимательного рассмотрения выяснилось, что возможно и баг, поскольку интел и комо этот код съедают и 7.3.3/12 тоже это подтверждает. Тем не менее, того что я написал это не отменяет. Поэтому теперь уже не знаю как правильно
--
Sergey Chadov

... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: error C2668: 'A::func' : ambiguous call
От: Starik_Hottabych  
Дата: 20.09.06 16:49
Оценка:
Здравствуйте, Лекс, Вы писали:

Л>Всем привет.


Л>Почему это не работает?


Л>
Л>class A
Л>{
Л>public:
Л>    void func()
Л>    {
Л>        cout << "A\n";
Л>    }
Л>};

Л>class B : public A
Л>{
Л>public:
Л>    bool func()         // ИСПРАВЛЕНИЕ №1. Если заменить на void func(), то все нормально
Л>    {
Л>        cout << "B\n";
Л>        return true;
Л>    }

Л>    void ssss()
Л>    {
Л>        B::func();    // С2668
Л>    }

Л>protected:
Л>    using A::func;      // ИСПРАВЛЕНИЕ №2. Закаментировать и все заработает 
Л>};
Л>



У Вас функций func() неправильно перегружена. Фактически у Вас написано, что класс B обладает следующими функциями

bool A::func()
bool B::func() //но объект производного класса является объектом базового!!

В качестве доказательства попробуйте в одной из функций изменить список параметров хотя бы так

bool A::func(int){//your code
}
Re[4]: error C2668: 'A::func' : ambiguous call
От: Vain Россия google.ru
Дата: 20.09.06 18:02
Оценка:
Здравствуйте, 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.]
[Даю очевидные ответы на риторические вопросы]
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.