Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 8, средняя оценка - 4.63
gromo
 Аватар для gromo
367 / 266 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
#1

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

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

Есть такая иерархия и 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} одновременно... ничего не идет в голову
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Olivеr
 Аватар для Olivеr
411 / 407 / 13
Регистрация: 06.10.2011
Сообщений: 830
26.10.2013, 23:42     Неоднозначность и multiple inheritance #2
менять можно только класс MI?
gromo
 Аватар для gromo
367 / 266 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
26.10.2013, 23:56  [ТС]     Неоднозначность и multiple inheritance #3
Цитата Сообщение от Olivеr Посмотреть сообщение
менять можно только класс MI?
Да. Так в упражнении в книге написано.

Добавлено через 12 минут
Единственное к чему я пришел - это добавить функцию MI:: print(string); но это неправильно с точки зрения ООП: ведь по логике нужно вызвать именно Base:: print(string);
Я в недоумении уже долго
Olivеr
 Аватар для Olivеr
411 / 407 / 13
Регистрация: 06.10.2011
Сообщений: 830
26.10.2013, 23:56     Неоднозначность и multiple inheritance #4
Вообще было бы неплохо сделать наследование Base виртуальным ( у Derived1 и Derived2 ). Потом дописать в MI using Base:rint и все будет работать
Jupiter
Каратель
Эксперт C++
6547 / 3967 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
27.10.2013, 00:05     Неоднозначность и multiple inheritance #5
gromo, полный текст задания можно?
gromo
 Аватар для gromo
367 / 266 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
27.10.2013, 00:16  [ТС]     Неоднозначность и multiple inheritance #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  
gromo
 Аватар для gromo
367 / 266 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
27.10.2013, 00:20  [ТС]     Неоднозначность и multiple inheritance #7
P.s. Это задание было перед началом раздела "Виртульное наследование". Видимо так авторы решили "подшутить" над читателем - ведь мне еще не было известно про эту возможность. Поломайте голову, новички, полезно
Jupiter
Каратель
Эксперт C++
6547 / 3967 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
27.10.2013, 00:22     Неоднозначность и multiple inheritance #8
Цитата Сообщение от gromo Посмотреть сообщение
Как изменить определение класса MI, чтобы этот фрагмент компилировался и выполнялся правильно?
с такой формулировкой можно:
1) просто MI унаследовать от Base
2) реализовать в MI соответствующую перегрузку для string
виртуальное наследование не подходит под такую формулировку задания
alsav22
5410 / 4806 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
27.10.2013, 00:22     Неоднозначность и multiple inheritance #9
Цитата Сообщение от gromo Посмотреть сообщение
Спаибо, это сработало. Да и нужды в директиве нет - ведь подобъект типа Base теперь только один.
И как это решение сочетается с заданием:
Цитата Сообщение от gromo Посмотреть сообщение
Как изменить определение класса MI, чтобы этот фрагмент компилировался и выполнялся правильно?
gromo
 Аватар для gromo
367 / 266 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
27.10.2013, 00:26  [ТС]     Неоднозначность и multiple inheritance #10
Цитата Сообщение от alsav22 Посмотреть сообщение
И как это решение сочетается с заданием:
Сам не понимаю, это, нверное, такой прикол от авторов. Как подготовка перед следующим этапом.
alsav22
5410 / 4806 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
27.10.2013, 00:32     Неоднозначность и multiple inheritance #11
Что за книга?
gromo
 Аватар для gromo
367 / 266 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
27.10.2013, 00:35  [ТС]     Неоднозначность и multiple inheritance #12
Цитата Сообщение от alsav22 Посмотреть сообщение
Что за книга?
Стенли Липпман, Жози Лажойе "C++ Primer" 3rd Edition.
Глава 18, Упр. 18.12 (сразу же перед разделом "Виртуальное наследование").
I.M.
 Аватар для I.M.
564 / 547 / 5
Регистрация: 16.12.2011
Сообщений: 1,389
27.10.2013, 01:06     Неоднозначность и multiple inheritance #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;}
};
alsav22
5410 / 4806 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
27.10.2013, 01:30     Неоднозначность и multiple inheritance #14
Странно... Студия подчёркивает Base :: print и dancer, но компилируется. mingw: mi.print(dancer) не пропускает.
gromo
 Аватар для gromo
367 / 266 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
27.10.2013, 03:10  [ТС]     Неоднозначность и multiple inheritance #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 тоже ругается. Вот незадача
ct0r
C++/Haskell
 Аватар для ct0r
1663 / 589 / 40
Регистрация: 19.08.2012
Сообщений: 1,212
Завершенные тесты: 1
27.10.2013, 03:34     Неоднозначность и multiple inheritance #16
Без написания собственной функции не обойтись, так как иначе имя print базового класса всегда будет скрыто.
Тут вначале мы приводим указатель к базовому классу Derived1, устраняя неоднозначность в иерархии наследования, а затем явным квалификатором получаем доступ к сокрытому имени.
C++
1
void print(string s) const { dynamic_cast<const Derived1 *>(this)->Base::print(s); }
DU
1479 / 1055 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
27.10.2013, 04:01     Неоднозначность и multiple inheritance #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;
}
ct0r
C++/Haskell
 Аватар для ct0r
1663 / 589 / 40
Регистрация: 19.08.2012
Сообщений: 1,212
Завершенные тесты: 1
27.10.2013, 04:42     Неоднозначность и multiple inheritance #18
Цитата Сообщение от DU Посмотреть сообщение
какой еще динамический каст. во первых - он не должен работать при отсутствии чего-нибудь виртуального.
во вторых - зачем динамический каст когда можно статический.
в третьих зачем каст, когда можно задать область из какой области видимости использовать принт внутри такой функции.
и в четвертых, зачем такая функция, когда это можно сделать и во внешнем по отношению к классу коде:
Прочитай постановку задачи.
Что нужно изменить в определении класса MI, чтобы устранить неоднозначность?
Значит Derived1, Derived2, main не трогаем. Поэтому using не канает, как и Derived::принты. Ну и теперь само собой тебе должно быть понятно, что еще одна функция и каст необходимы. Да и плюс изменение интерфейса базовых классов без необходимости не тру в любом случае.

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

Добавлено через 13 минут
В общем добавлю, что при простом приведении объекта производного класса к непосредственному базовому, dynamic_cast работает не только с полиморфными типами. Более того, тут нет RTTI, а поэтому именно в данном случае нет никакого отличия от static_cast, даже в скорости.
gromo
 Аватар для gromo
367 / 266 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
27.10.2013, 05:24  [ТС]     Неоднозначность и multiple inheritance #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, она мне больше нравится)

MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
27.10.2013, 11:58     Неоднозначность и multiple inheritance
Еще ссылки по теме:

C++ Неоднозначность при наследовании
Неоднозначность переменной count C++
C++ Виртуальная неоднозначность
Неоднозначность декларации C++
Неоднозначность при множественном наследовании C++

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

Или воспользуйтесь поиском по форуму:
Jupiter
Каратель
Эксперт C++
6547 / 3967 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
27.10.2013, 11:58     Неоднозначность и multiple inheritance #20
Цитата Сообщение от ct0r Посмотреть сообщение
В общем добавлю, что при простом приведении объекта производного класса к непосредственному базовому, dynamic_cast работает не только с полиморфными типами. Более того, тут нет RTTI, а поэтому именно в данном случае нет никакого отличия от static_cast, даже в скорости.
пруф?
Yandex
Объявления
27.10.2013, 11:58     Неоднозначность и multiple inheritance
Ответ Создать тему
Опции темы

Текущее время: 00:54. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru