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

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

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

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

26.10.2013, 23:37. Просмотров 1078. Ответов 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} одновременно... ничего не идет в голову
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
26.10.2013, 23:37
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Неоднозначность и multiple inheritance (C++):

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

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

Templates. (concrete inheritance). question to destructor implementation - C++
Есть вот такой вот проект. Идея в том том что конкретный класс наследуется от темплейта. Как в таком случае ПРАВИЛЬНО + ГРАМОТНО...

Неоднозначность декларации - C++
Итак уважаемые знатоки: class Foo{ public: Foo(){}; }; Foo Bar(); Внимание вопрос: как уважающий себя...

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

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

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
ct0r
Игогошка!
1770 / 672 / 42
Регистрация: 19.08.2012
Сообщений: 1,284
Завершенные тесты: 1
27.10.2013, 03:34 #16
Без написания собственной функции не обойтись, так как иначе имя print базового класса всегда будет скрыто.
Тут вначале мы приводим указатель к базовому классу Derived1, устраняя неоднозначность в иерархии наследования, а затем явным квалификатором получаем доступ к сокрытому имени.
C++
1
void print(string s) const { dynamic_cast<const Derived1 *>(this)->Base::print(s); }
DU
1483 / 1059 / 45
Регистрация: 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;
}
ct0r
Игогошка!
1770 / 672 / 42
Регистрация: 19.08.2012
Сообщений: 1,284
Завершенные тесты: 1
27.10.2013, 04:42 #18
Цитата Сообщение от DU Посмотреть сообщение
какой еще динамический каст. во первых - он не должен работать при отсутствии чего-нибудь виртуального.
во вторых - зачем динамический каст когда можно статический.
в третьих зачем каст, когда можно задать область из какой области видимости использовать принт внутри такой функции.
и в четвертых, зачем такая функция, когда это можно сделать и во внешнем по отношению к классу коде:
Прочитай постановку задачи.
Что нужно изменить в определении класса MI, чтобы устранить неоднозначность?
Значит Derived1, Derived2, main не трогаем. Поэтому using не канает, как и Derived::принты. Ну и теперь само собой тебе должно быть понятно, что еще одна функция и каст необходимы. Да и плюс изменение интерфейса базовых классов без необходимости не тру в любом случае.

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

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

Jupiter
Каратель
Эксперт С++
6553 / 3973 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
27.10.2013, 11:58 #20
Цитата Сообщение от ct0r Посмотреть сообщение
В общем добавлю, что при простом приведении объекта производного класса к непосредственному базовому, dynamic_cast работает не только с полиморфными типами. Более того, тут нет RTTI, а поэтому именно в данном случае нет никакого отличия от static_cast, даже в скорости.
пруф?
ct0r
Игогошка!
1770 / 672 / 42
Регистрация: 19.08.2012
Сообщений: 1,284
Завершенные тесты: 1
27.10.2013, 12:05 #21
Цитата Сообщение от Jupiter Посмотреть сообщение
пруф?
5.2.7.5, 5.2.7.6
Jupiter
Каратель
Эксперт С++
6553 / 3973 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
27.10.2013, 12:09 #22
Цитата Сообщение от ct0r Посмотреть сообщение
Более того, тут нет RTTI, а поэтому именно в данном случае нет никакого отличия от static_cast, даже в скорости.
ещё пруф?
ct0r
Игогошка!
1770 / 672 / 42
Регистрация: 19.08.2012
Сообщений: 1,284
Завершенные тесты: 1
27.10.2013, 12:30 #23
Цитата Сообщение от Jupiter Посмотреть сообщение
ещё пруф?
Тебе не очевидно, что RTTI не включается в неполиморфные типы? Или ты думаешь, что проверка откладывается на рантайм (где осуществляется с помощью RTTI), когда она может быть элементарно разрулена в компайл-тайм?
Jupiter
Каратель
Эксперт С++
6553 / 3973 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
27.10.2013, 13:15 #24
Цитата Сообщение от ct0r Посмотреть сообщение
Тебе не очевидно, что RTTI не включается в неполиморфные типы? Или ты думаешь, что проверка откладывается на рантайм (где осуществляется с помощью RTTI), когда она может быть элементарно разрулена в компайл-тайм?
ни разу не очевидно. в с++ нельзя полагаться на очевидность.
вот стоял бы там какой-нибудь boost:: polymorphic_cast тогда да.
ct0r
Игогошка!
1770 / 672 / 42
Регистрация: 19.08.2012
Сообщений: 1,284
Завершенные тесты: 1
27.10.2013, 13:42 #25
Цитата Сообщение от Jupiter Посмотреть сообщение
ни разу не очевидно. в с++ нельзя полагаться на очевидность.
вот стоял бы там какой-нибудь boost:: polymorphic_cast тогда да.
Хорошо. Пруф от Страуструпа
This (the upcast) is the uninteresting case. However, it is reassuring to know that dynamic_cast doesn’t allow accidental violation of the protection of private and protected base classes. Since a dynamic_cast used as an upcast is exactly like a simple assignment, it implies no overhead and is sensitive to its lexical context.
The purpose of dynamic_cast is to deal with the case in which the correctness of the conversion cannot be determined by the compiler.
Кстати причем тут polymorphic_cast? Это просто обертка. Может ты имел ввиду polymorphic_downcast, который в режиме NDEBUG превращается в static_cast? Но, так или иначе, риторический вопрос: почему polymorphic_downcast есть, а polymorphic_upcast нету?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
27.10.2013, 13:42
Привет! Вот еще темы с ответами:

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

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

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

компилятор находит неоднозначность при вызове round(i) - C++
Доброго времени суток! Подскажите, компилятор находит неодназначтность в строке 26 *вызов функции round(i)* ...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
27.10.2013, 13:42
Ответ Создать тему
Опции темы

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