Перегрузка метода при множественном наследовании.
От: Maxim Lock Россия  
Дата: 12.03.04 19:25
Оценка:
Приветствую, господа, и, дамы, если есть, конечно тоже.

Попробовал поискать здесь и в инете, но безуспешно. Если коротко, пример:

class P1 {}; 
class P2 {};

class A
{
public:
    void f( P1* );
};

class B
{
public:
    void f( P2* );
};

class C : 
    public A, 
    public B
{
public:
    C()
    {
        P2* p;
        f( p );
    }
};

int main()
{
    C q;
}


на что например ICL (уверен, что справедливо) отвечает:

test1.cpp
test1.cpp(18): error: "С::f" is ambiguous
f( p );
^

Почему не разрешена такая перегрузка, с точки зрения компилятора — все однозначно. Можно просто указать пункт стандарта в котором описана данная ситуация, я не нашел.

В моей ситуции указывать явно имя базового класса при вызове f() нельзя, (хотя бы потому что оно очень длинное, это шаблон). Хочется найти элегантное решение.

Спасибо.

Исправлена раскраска — WH
... << RSDN@Home 1.1.3 beta 1 >>
Re: Вопрос по шаблонам
От: _Winnie Россия C++.freerun
Дата: 12.03.04 19:34
Оценка: +1

class P1 {};
class P2 {};

class Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
{
public:
  void f( P1* );
};

class Bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
{
public:
  void f( P2* ) {};
};

typedef Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa A;
typedef Bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb B;


class C :
public A,
public B
{
public:
  C()
  {
    P2* p;
    B::f( p );
  }
};

int main()
{
  C q;
}

Исправлена раскраска — WH
Правильно работающая программа — просто частный случай Undefined Behavior
Re[2]: Вопрос по шаблонам
От: Maxim Lock Россия  
Дата: 12.03.04 20:43
Оценка:
Здравствуйте, _Winnie, Вы писали:

Удалено избыточное цитирование — WH

Замечательно, но почему typedef такие чудеса сотворил?! Почему без него перегрузка корректно не разрешается?
... << RSDN@Home 1.1.3 beta 1 >>
Re[3]: Вопрос по шаблонам
От: v0id  
Дата: 12.03.04 21:51
Оценка:
Здравствуйте, Maxim Lock, Вы писали:

ML>Замечательно, но почему typedef такие чудеса сотворил?! Почему без него перегрузка корректно не разрешается?


Удалено избыточное цитирование — WH

..По-моему ,ничего здесь typedef не сотворил .B:: сотворил.Судя по всему классы A(Aaaaaaaaaaaaaaa) и B (Bbbbbbbbbbbb) схожи по структуре(указатель на один можно легко переопределить в указатель на другой) и ..естессно компилятор не решается вызвать тот или иной метод f().
В книге Б. Страуструпа описана такая ситуация,как одна из встречающихся ошибок...
Re[4]: Вопрос по шаблонам
От: Maxim Lock Россия  
Дата: 14.03.04 06:26
Оценка:
Удалено избыточное цитирование — WH

V>..По-моему ,ничего здесь typedef не сотворил .B:: сотворил.Судя по всему классы A(Aaaaaaaaaaaaaaa) и B (Bbbbbbbbbbbb) схожи по структуре(указатель на один можно легко переопределить в указатель на другой) и ..естессно компилятор не решается вызвать тот или иной метод f().

V>В книге Б. Страуструпа описана такая ситуация,как одна из встречающихся ошибок

Да, нехорошо так издеваться, спасибо, что сказал, а я добавленный B:: перед f не заметил, подумал что это typedef колдовство

К сожалению, нельзя использовать явное указание базового класса в моем случае. Все очень просто на самом деле, хочется чтобы в классе унаследованном от одного/двух/.../n разных специализаций шаблона, можно было использовать вызовы метода из одного из базового класса, с одинаковым именем, но сторогим соответствием типа аргумента. Обычная перегрузка это позволяет, так в чем разница, (методы не виртуальные).

Так вопрос в силе! ну скажите, в чем проблема почему так нельзя перегрузить методы через базовые класы?! Или как это можно красиво обойти, "обертки" какие-то может сделать ...
Re[5]: Вопрос по шаблонам
От: Tonal- Россия www.promsoft.ru
Дата: 14.03.04 11:45
Оценка:
ML>Да, нехорошо так издеваться, спасибо, что сказал, а я добавленный B:: перед f не заметил, подумал что это typedef колдовство

ML>К сожалению, нельзя использовать явное указание базового класса в моем случае. Все очень просто на самом деле, хочется чтобы в классе унаследованном от одного/двух/.../n разных специализаций шаблона, можно было использовать вызовы метода из одного из базового класса, с одинаковым именем, но сторогим соответствием типа аргумента. Обычная перегрузка это позволяет, так в чем разница, (методы не виртуальные).


ML>Так вопрос в силе! ну скажите, в чем проблема почему так нельзя перегрузить методы через базовые класы?! Или как это можно красиво обойти, "обертки" какие-то может сделать ...


Действительно, это запрещено стандартом. Для обяснения читай Страуструпа.
А обойти это можно только явно указав использование обоих имён в области видимости класса:
class C : public A, public B {
  using A::f;
  using B::f;
  C() {
    P2* p = 0;
    f(p);
  }
};

Или написать промежуточный классик:
class Immediate : public A, public B {
  using A::f;
  using B::f;
};
class C : public Immediate {
  C() {
    P2* p = 0;
    f(p);
  }
};

Который можно сделать шаблонным спомощью списков типов.
... << RSDN@Home 1.1.3 stable >>
Re[6]: Вопрос по шаблонам
От: Maxim Lock Россия  
Дата: 14.03.04 16:55
Оценка:
Удалено избыточное цитирование — WH

T>Действительно, это запрещено стандартом. Для обяснения читай Страуструпа.

T>А обойти это можно только явно указав использование обоих имён в области видимости класса:
Удалено избыточное цитирование — WH
T>Который можно сделать шаблонным спомощью списков типов.

Спасибо, интересный вариант, но опять к сожалению нужно указывать явно базовый класс, и список типов я под vc6 использовать не смогу (я знаю про порт Loki для vc6 by Rani Sharoni, но мы его не используем), да и он помог бы лишь отчасти.

Я хочу попробовать вариант с шаблонной базовой функцией, которая по типу аргумента все же "перенаправляет" явно вызов у нужному родительскому классу, что-то вроде статического patterna'а visitor, если интересно — расскажу, что получилось (но пока не получилось )
Re: Перегрузка метода при множественном наследовании.
От: Аноним  
Дата: 14.03.04 17:03
Оценка:
Если ты хочешь ссылку на стандарт, читаи clause 10, 3.
До того, как сработает разрешение перегрузки, происходит поиск имен. Имя f — неоднозначно.
Re: Перегрузка метода при множественном наследовании.
От: Аноним  
Дата: 15.03.04 12:50
Оценка:
Здравствуйте, Maxim Lock, Вы писали:

ML>Почему не разрешена такая перегрузка, с точки зрения компилятора — все однозначно. Можно просто указать пункт стандарта в котором описана данная ситуация, я не нашел.


ML>В моей ситуции указывать явно имя базового класса при вызове f() нельзя, (хотя бы потому что оно очень длинное, это шаблон). Хочется найти элегантное решение.


Насколько я помню, разрешение имен в этом случае идет буз ечета аргументов. Поэтому необходимо четко указывать базовый класс или использовыать using.
Re[2]: Перегрузка метода при множественном наследовании.
От: Maxim Lock Россия  
Дата: 16.03.04 08:16
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Если ты хочешь ссылку на стандарт, читаи clause 10, 3.

А>До того, как сработает разрешение перегрузки, происходит поиск имен. Имя f — неоднозначно.

Спасибо, вы правы.
Re[2]: Перегрузка метода при множественном наследовании.
От: Maxim Lock Россия  
Дата: 16.03.04 08:17
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Насколько я помню, разрешение имен в этом случае идет буз ечета аргументов. Поэтому необходимо четко указывать базовый класс или использовыать using.


Да, спасибо, так оно и есть.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.