Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.82/11: Рейтинг темы: голосов - 11, средняя оценка - 4.82
383 / 281 / 31
Регистрация: 04.09.2009
Сообщений: 1,225
1

Неоднозначность и multiple inheritance

26.10.2013, 23:37. Показов 2001. Ответов 24
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Есть такая иерархия и main():
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include <string>
#include <complex>
using namespace std;
 
class Base {
public:
    void print(string s) const { cout <<"Base::print(string)" <<endl;}
};
 
class Derived1 : public Base {
public:
    void print(int i) const {cout <<"Derived1::print(int)" <<endl;}
};
 
class Derived2 : public Base {
public:
    void print(double d) const {cout <<"Derived2::print(double)" <<endl;}
};
 
class MI : public Derived1, public Derived2 {
public:
    void print (complex<double> cd) const {cout <<"MI::print(complex<double>)" <<endl;}
};
 
int main()
{
    MI mi;
    string dancer("ASD");
    mi.print(dancer);
    return 0;
}
Что нужно изменить в определении класса MI, чтобы устранить неоднозначность? Квалификация Base:: print при вызове не помогает, так как он базовый для двух классов Derived1{,2} одновременно... ничего не идет в голову
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
26.10.2013, 23:37
Ответы с готовыми решениями:

Inheritance
Доброго времени суток. Роберт Лафоре &quot;ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ В C++&quot;, 2004 год....

Generic inheritance. Templates
Код компилируется. Не могу разобраться то ли я как не правильно иерархию построил то ли...

Copy Constructor Question .Generic inheritance. Templates
Допустим есть проект // // (---.Array_hpp---) // #ifndef...

Templates. (concrete inheritance). question to destructor implementation
Есть вот такой вот проект. Идея в том том что конкретный класс наследуется от темплейта. Как в...

24
415 / 411 / 95
Регистрация: 06.10.2011
Сообщений: 832
26.10.2013, 23:42 2
менять можно только класс MI?
0
383 / 281 / 31
Регистрация: 04.09.2009
Сообщений: 1,225
26.10.2013, 23:56  [ТС] 3
Цитата Сообщение от Olivеr Посмотреть сообщение
менять можно только класс MI?
Да. Так в упражнении в книге написано.

Добавлено через 12 минут
Единственное к чему я пришел - это добавить функцию MI:: print(string); но это неправильно с точки зрения ООП: ведь по логике нужно вызвать именно Base:: print(string);
Я в недоумении уже долго
0
415 / 411 / 95
Регистрация: 06.10.2011
Сообщений: 832
26.10.2013, 23:56 4
Вообще было бы неплохо сделать наследование Base виртуальным ( у Derived1 и Derived2 ). Потом дописать в MI using Base:rint и все будет работать
1
Каратель
Эксперт С++
6609 / 4028 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
27.10.2013, 00:05 5
gromo, полный текст задания можно?
0
383 / 281 / 31
Регистрация: 04.09.2009
Сообщений: 1,225
27.10.2013, 00:16  [ТС] 6
Цитата Сообщение от Jupiter Посмотреть сообщение
полный текст задания можно?
Как изменить определение класса MI, чтобы этот фрагмент компилировался и выполнялся правильно?
Цитата Сообщение от Olivеr Посмотреть сообщение
Вообще было бы неплохо сделать наследование Base виртуальным ( у Derived1 и Derived2 ). Потом дописать в MI using Base:rint и все будет работать
Спаибо, это сработало. Да и нужды в директиве нет - ведь подобъект типа Base теперь только один.

Добавлено через 1 минуту
Исправленный вариант, может кому пригодится:
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include <string>
#include <complex>
using namespace std;
 
class Base {
public:
    void print(string s) const { cout <<"Base::print(string)" <<endl;}
};
 
class Derived1 : virtual public Base {
public:
    void print(int i) const {cout <<"Derived1::print(int)" <<endl;}
};
 
class Derived2 : public virtual Base {
public:
    void print(double d) const {cout <<"Derived2::print(double)" <<endl;}
};
 
class MI : public Derived1, public Derived2 {
public:
    void print (complex<double> cd) const {cout <<"MI::print(complex<double>)" <<endl;}
};
 
int main()
{
    MI mi;
    string dancer("ASD");
    mi.print(dancer);
    return 0;
}
Миниатюры
Неоднозначность и multiple inheritance  
0
383 / 281 / 31
Регистрация: 04.09.2009
Сообщений: 1,225
27.10.2013, 00:20  [ТС] 7
P.s. Это задание было перед началом раздела "Виртульное наследование". Видимо так авторы решили "подшутить" над читателем - ведь мне еще не было известно про эту возможность. Поломайте голову, новички, полезно
0
Каратель
Эксперт С++
6609 / 4028 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
27.10.2013, 00:22 8
Цитата Сообщение от gromo Посмотреть сообщение
Как изменить определение класса MI, чтобы этот фрагмент компилировался и выполнялся правильно?
с такой формулировкой можно:
1) просто MI унаследовать от Base
2) реализовать в MI соответствующую перегрузку для string
виртуальное наследование не подходит под такую формулировку задания
0
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
27.10.2013, 00:22 9
Цитата Сообщение от gromo Посмотреть сообщение
Спаибо, это сработало. Да и нужды в директиве нет - ведь подобъект типа Base теперь только один.
И как это решение сочетается с заданием:
Цитата Сообщение от gromo Посмотреть сообщение
Как изменить определение класса MI, чтобы этот фрагмент компилировался и выполнялся правильно?
0
383 / 281 / 31
Регистрация: 04.09.2009
Сообщений: 1,225
27.10.2013, 00:26  [ТС] 10
Цитата Сообщение от alsav22 Посмотреть сообщение
И как это решение сочетается с заданием:
Сам не понимаю, это, нверное, такой прикол от авторов. Как подготовка перед следующим этапом.
0
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
27.10.2013, 00:32 11
Что за книга?
0
383 / 281 / 31
Регистрация: 04.09.2009
Сообщений: 1,225
27.10.2013, 00:35  [ТС] 12
Цитата Сообщение от alsav22 Посмотреть сообщение
Что за книга?
Стенли Липпман, Жози Лажойе "C++ Primer" 3rd Edition.
Глава 18, Упр. 18.12 (сразу же перед разделом "Виртуальное наследование").
0
576 / 559 / 47
Регистрация: 16.12.2011
Сообщений: 1,389
27.10.2013, 01:06 13
C++
1
2
3
4
5
class MI : public Derived1, public Derived2 {
public:
    using Base::print;
    void print (complex<double> cd) const {cout <<"MI::print(complex<double>)" <<endl;}
};
0
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
27.10.2013, 01:30 14
Странно... Студия подчёркивает Base :: print и dancer, но компилируется. mingw: mi.print(dancer) не пропускает.
0
383 / 281 / 31
Регистрация: 04.09.2009
Сообщений: 1,225
27.10.2013, 03:10  [ТС] 15
Цитата Сообщение от I.M. Посмотреть сообщение
C++ (Qt)
1
2
3
4
5
class MI : public Derived1, public Derived2 {
public:
     using Base::print;
     void print (complex<double> cd) const {cout <<"MI::print(complex<double>)" <<endl;}
};
нее, так тоже неоднозначность: функции какого подобъекта вводить в область видимости MI: Derived1::Base или Derived2::Base ?
Цитата Сообщение от alsav22 Посмотреть сообщение
Странно... Студия подчёркивает Base :: print и dancer, но компилируется. mingw: mi.print(dancer) не пропускает.
Да уж, действительно странно. У меня GCC 4.8.2 тоже ругается. Вот незадача
0
Игогошка!
1801 / 708 / 44
Регистрация: 19.08.2012
Сообщений: 1,367
27.10.2013, 03:34 16
Без написания собственной функции не обойтись, так как иначе имя print базового класса всегда будет скрыто.
Тут вначале мы приводим указатель к базовому классу Derived1, устраняя неоднозначность в иерархии наследования, а затем явным квалификатором получаем доступ к сокрытому имени.
C++
1
void print(string s) const { dynamic_cast<const Derived1 *>(this)->Base::print(s); }
1
DU
1500 / 1146 / 165
Регистрация: 05.12.2011
Сообщений: 2,279
27.10.2013, 04:01 17
какой еще динамический каст. во первых - он не должен работать при отсутствии чего-нибудь виртуального.
во вторых - зачем динамический каст когда можно статический.
в третьих зачем каст, когда можно задать область из какой области видимости использовать принт внутри такой функции.
и в четвертых, зачем такая функция, когда это можно сделать и во внешнем по отношению к классу коде:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <iostream>
#include <string>
#include <complex>
 
using namespace std;
 
class Base
{
public:
  void print(const string s) const
  {
    cout <<"Base::print(string)" <<endl;
  }
};
 
class Derived1 : public Base
{
public:
  using Base::print;
 
  void print(int i) const
  {
    cout <<"Derived1::print(int)" <<endl;
  }
};
 
class Derived2 : public Base
{
public:
  using Base::print;
 
  void print(double d) const
  {
    cout <<"Derived2::print(double)" <<endl;
  }
};
 
class MI : public Derived1, public Derived2
{
public:
  using Derived1::print;
  using Derived2::print;
 
  void print(const complex<double>& cd) const
  {
    cout <<"MI::print(complex<double>)" <<endl;
  }
};
 
int main()
{
  string str("str");
  int i = 0;
  double d = 0;
  complex<double> c;
 
  MI mi;
  mi.Derived1::print(str); // если не хотим виртуально наследоватсья
  mi.Derived2::print(str); // то придется явно указывать область.
  mi.print(i);
  mi.print(d);
  mi.print(c);
  cout << "done" << endl;
 
  return 0;
}
0
Игогошка!
1801 / 708 / 44
Регистрация: 19.08.2012
Сообщений: 1,367
27.10.2013, 04:42 18
Цитата Сообщение от DU Посмотреть сообщение
какой еще динамический каст. во первых - он не должен работать при отсутствии чего-нибудь виртуального.
во вторых - зачем динамический каст когда можно статический.
в третьих зачем каст, когда можно задать область из какой области видимости использовать принт внутри такой функции.
и в четвертых, зачем такая функция, когда это можно сделать и во внешнем по отношению к классу коде:
Прочитай постановку задачи.
Что нужно изменить в определении класса MI, чтобы устранить неоднозначность?
Значит Derived1, Derived2, main не трогаем. Поэтому using не канает, как и Derived::принты. Ну и теперь само собой тебе должно быть понятно, что еще одна функция и каст необходимы. Да и плюс изменение интерфейса базовых классов без необходимости не тру в любом случае.

И покажи мне пункт стандарта, который запрещает мне использовать dynamic_cast в данном случае (хоть и нет полиморфности). Но да, static_cast тоже можно использовать.

Добавлено через 13 минут
В общем добавлю, что при простом приведении объекта производного класса к непосредственному базовому, dynamic_cast работает не только с полиморфными типами. Более того, тут нет RTTI, а поэтому именно в данном случае нет никакого отличия от static_cast, даже в скорости.
0
383 / 281 / 31
Регистрация: 04.09.2009
Сообщений: 1,225
27.10.2013, 05:24  [ТС] 19
Цитата Сообщение от ct0r Посмотреть сообщение
Без написания собственной функции не обойтись, так как иначе имя print базового класса всегда будет скрыто.
Тут вначале мы приводим указатель к базовому классу Derived1, устраняя неоднозначность в иерархии наследования, а затем явным квалификатором получаем доступ к сокрытому имени.
C++ (Qt)
1
void print(string s) const { dynamic_cast<const Derived1 *>(this)->Base::print(s); }
Вот это навернули)) И изменили только класс MI, и без виртуального наследования обошлись.

Не по теме:

P.s. sorry за подсветку синтаксиса Qt, она мне больше нравится)

0
Каратель
Эксперт С++
6609 / 4028 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
27.10.2013, 11:58 20
Цитата Сообщение от ct0r Посмотреть сообщение
В общем добавлю, что при простом приведении объекта производного класса к непосредственному базовому, dynamic_cast работает не только с полиморфными типами. Более того, тут нет RTTI, а поэтому именно в данном случае нет никакого отличия от static_cast, даже в скорости.
пруф?
0
27.10.2013, 11:58
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
27.10.2013, 11:58
Помогаю со студенческими работами здесь

Неоднозначность декларации
Итак уважаемые знатоки: class Foo{ public: Foo(){}; }; Foo Bar(); Внимание...

Виртуальная неоднозначность
Не понимаю пример из книги С.Праты: class B { public: short q(); }; class C : virtual...

неоднозначность, explicit
Добрый вечер. написал такой шаблонный класс: template &lt;class T&gt; class Container { ...

Неоднозначность при наследовании
Привет народ, думаю мой вопрос покажется вам чем-то из разряда &quot;лучше бы делом занялся&quot;, но тех у...

Неоднозначность переменной count
Доброго времени суток. Использую VS2013. Подскажите пожалуйста, по какой причине глобальная...

Неоднозначность при множественном наследовании
Привет всем, столкнулся с проблемой при множественном наследовании классов. Надеюсь, кто-нибудь...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru