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

Вопрос по наследованию - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 17, средняя оценка - 4.82
ramarren14
2 / 2 / 0
Регистрация: 14.07.2011
Сообщений: 49
09.11.2011, 17:48     Вопрос по наследованию #1
Уже неоднократно перечитывал главы про наследования и все равно до конца не разобрался.
Вот например у нас есть класс Четырехугольник, и мы создаем класс Прямоугольник.
И в том и в другом классе есть функции Площадь и если у них будет одинаковая сигнатура, то вызовется функция того класса, объект которого мы создали. Если же сигнатуры совпадать не будут, то нужно явно указать с помощью оператора ::.
Если мы сделаем функцию площади виртуальной, то при одинаковых сигнатурах вызовется функция своего класса. То же в случае разных сигнатур. То есть единственный плюс объявления функций виртуальными, это то что если мы создадим указатель на объект базового класса, он сможет указывать и на объект производного класса?
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Deviaphan
Делаю внезапно и красиво
Эксперт C++
 Аватар для Deviaphan
1283 / 1217 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
10.11.2011, 20:30     Вопрос по наследованию #41
Цитата Сообщение от LosAngeles Посмотреть сообщение
Переключаем версию на релиз и нет никаких ассертов, что мы получаем?
Как бы игнорирование ошибки не есть её исправление...
Отключать ассерты в релизе не есть хорошо. Стандартный ассерт УГ, сакс и фтопку.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Bers
Заблокирован
10.11.2011, 20:35     Вопрос по наследованию #42
Цитата Сообщение от Deviaphan Посмотреть сообщение
Ведь согласись, что следующая реализация метода не может быть у квадрата
Да, не может. Поэтому, квадрат можно отнаследовать от прямоугольника, но нельзя отнаследовать от кирпича.

Если ваш манипулятор ожидает на входе кирпич, то он и должен принимать только кирпичи, а не все мыслимые и не мыслимые прямоугольники.

Если манипулятор ожидает на входе все мыслимые и не мыслимые прямоугольники, то он должен быть готов к тому, что придти может и кирпич, и квадрат.

Если манипулятор не делает различий между кирпичом и квадратом, но в рантайме ломает все квадраты - это архитектурный фейл.

Проектирование по принципу: "Я не запрещаю тебе быть квадратом, но если ты реально окажется квадратом, то я заломаю нафег всю программу"

Это проектирование по принципу: "Здесь, здесь и здесь я закопаю мину. Специально, что бы взрывать полностью работоспособный процесс".

Добавлено через 2 минуты
Цитата Сообщение от LosAngeles Посмотреть сообщение
Переключаем версию на релиз и нет никаких ассертов, что мы получаем?
Кашу в голове, и мину замедленного действия в коде мы получаем. И программиста, который не вполне себе осознает, для чего вообще существуют ассерты
Le Thaw
10.11.2011, 20:37
  #43

Не по теме:

Bers, зачетные цитаты.

LosAngeles
Заблокирован
10.11.2011, 20:39     Вопрос по наследованию #44
Цитата Сообщение от Deviaphan Посмотреть сообщение
Совершенно верно! Метод должен называться MakeWidthBigger и тогда он становится правильным. С данным названием он недоопределён и его поведение зависит от фактического типа объекта, что не есть хорошо.
нет, от изменения названия он правильнее не станет ни на йоту. Я вправе ожидать от квадрата, что его стороны будут равны друг другу в любой момент времени, а не подбирать функцию исходя из её названия(что за лол?) и гадать, а не приведёт ли она квадрат в противоречивое состояние, что в случае наследования от прямоугольника сделать легко. Так что если найдётся хоть один способ привести квадрат в противоречивое состояние через его же интерфейс, значит вся иерархия тухлая.
Bers
Заблокирован
10.11.2011, 20:41     Вопрос по наследованию #45
Цитата Сообщение от Deviaphan Посмотреть сообщение
но реализация полиморфизма никак не регламентирована и разработчики компиляторов вольны реализовывать его как им вздумается. Поэтому о "низкоуровневой" реализации лучше даже и не задумываться. Только если с привязкой к компилятору.
Ну как бы, на самом деле и не нужно об этом задумываться. Нужно просто понимать, как он должен работать.

Главный принцип: указатель базового типа запустит метод потомка, если сам указатель будит указывать на этого потомка, а сам метод будит виртуальным.

Если метод будит не виртуальным, запустится базовый метод.

По моему, вполне достаточно для понимания)
LosAngeles
Заблокирован
10.11.2011, 20:41     Вопрос по наследованию #46
Цитата Сообщение от Bers Посмотреть сообщение
Кашу в голове, и мину замедленного действия в коде мы получаем. И программиста, который не вполне себе осознает, для чего вообще существуют ассерты
всё это на мыло мейерсу скинить и его боссу, давно пора уволить этого идиота, а книжки сжечь!
Deviaphan
Делаю внезапно и красиво
Эксперт C++
 Аватар для Deviaphan
1283 / 1217 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
10.11.2011, 20:43     Вопрос по наследованию #47
Цитата Сообщение от Bers Посмотреть сообщение
Поэтому, квадрат можно отнаследовать от прямоугольника
Ну как может-то?
Есть метод изменения ширины, который должен изменять ширину. В квадрате же он должен синхронно изменять и высоту. Метод "ИзменитьШирину", который изменяет высоту это ведь не правильно. С этим ты готов согласиться? Это нарушение логики. Т.е. для квадрата методы ЗадатьШирину и ЗадатьВысоту должны быть закрыты и вместо них должен быть добавлен метод ЗадатьРазмер. Т.е. квадрат не является прямоугольником с точки зрения интерфейса (с точки зрения геометрии, разумеется, он является прямоугольником и четырёхугольником), и если и можно его наследовать, то только закрытым наследованием от rectangle.
Сыроежка
Заблокирован
10.11.2011, 20:43     Вопрос по наследованию #48
Цитата Сообщение от LosAngeles Посмотреть сообщение
всё это на мыло мейерсу скинить и его боссу, давно пора уволить этого идиота, а книжки сжечь!
Вы путаете себя с Майерсом! Не надо себя отождествлять с Майерсом. Старайтесь говорить от себя лично и приводить конкретные примеры, которые убеждают в вашей правоте.
Deviaphan
Делаю внезапно и красиво
Эксперт C++
 Аватар для Deviaphan
1283 / 1217 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
10.11.2011, 20:46     Вопрос по наследованию #49
Цитата Сообщение от LosAngeles Посмотреть сообщение
он правильнее не станет ни на йоту
Станет. В нём будет разрешено изменение ширины и запрещено изменение высоты. Что будет соответствовать названию. Слово СделатьБольше не уточняет, каким именно образом он будет становиться больше, поэтому запрет изменения высоты не корректен.

Добавлено через 1 минуту
Цитата Сообщение от Bers Посмотреть сообщение
о моему, вполне достаточно для понимания
Абсолютно да.) Просто слово "низкоуровневое" наводит на более глубокие изыскания.)
Bers
Заблокирован
10.11.2011, 21:02     Вопрос по наследованию #50
Цитата Сообщение от Deviaphan Посмотреть сообщение
Есть метод изменения ширины, который должен изменять ширину. В квадрате же он должен синхронно изменять и высоту. Метод "ИзменитьШирину", который изменяет высоту это ведь не правильно. С этим ты готов согласиться? Это нарушение логики. Т.е. для квадрата методы ЗадатьШирину и ЗадатьВысоту должны быть закрыты и вместо них должен быть добавлен метод ЗадатьРазмер. Т.е. квадрат не является прямоугольником с точки зрения интерфейса
Я не согласен.
Для прямоугольника: Изменяем высоту - изменится высота.
Изменяем ширину - изменится ширина.

Для квадрата - изменяем хоть ширину, хоть высоту. Все равно запускается родной для квадрата метод "изменить размер"

То есть метод "изменить ширину" для квадрата такой же правомерный, как и для любого другого прямоугольника. Но реализация метода отличается тем, что для квадрата изменится не только ширина, но и высота.

Я имею полное право изменить ширину квадрата. Что мне мешает это сделать?
Я не имею права для квадрата изменить ширину, а высоту оставить прежней. Но об этом контракте позаботится сам квадрат. Его реализации методов "изменить ширину/высоту".

Для прямоугольника метод "изменить ширину" - изменит ширину фигуры.
При этом, может изменится и высота, если фигура - квадрат. Что здесь нелогичного?

Я хочу сказать, что у прямоугольника при изменении ширины, высота не обязана сохранять прежнее значение.

Вы можете сказать: но это тупо! Зачем квадрату вообще иметь методы "изменить ширину/высоту", если идеологически ему нужен только один метод "ИзменитьРазмер" ?

Тут я с вами соглашусь полностью. Для квадрата первые два интерфейса кажутся излишними.
Но это - зависит от архитектурного решения. Такое решение может быть не самое красивое, с точки зрения минимализма, но вполне приемлимое.

Об этом и пишет Маерс (я по крайней мере так его понял) - о том, что оо-программирование, это в первую очередь программирование в терминах интерфейсов.

И при установлении различных отношений между классами, в первую очередь нужно согласовывать интерфейсы предков и потомков, что бы не получилось "аляписто".

Что бы не пришлось на некоторые методы вообще ставить заглушки (метод как бы есть, а использовать его нельзя).

Что бы не получилось что методов больше, чем требуется объекту по смыслу.

Хотя пример для иллюстрации он привел фейловый

Добавлено через 1 минуту

Не по теме:

Цитата Сообщение от Deviaphan Посмотреть сообщение
Абсолютно да.) Просто слово "низкоуровневое" наводит на более глубокие изыскания.)
ну это я так, понтануццо просто хотел))
Заодно интересную ссылку народу предоставил)

ValeryLaptev
Эксперт C++
1004 / 783 / 46
Регистрация: 30.04.2011
Сообщений: 1,595
10.11.2011, 21:31     Вопрос по наследованию #51
Цитата Сообщение от Chelioss Посмотреть сообщение
С указателями понятно. Без виртуальности будет вызываться метод класса Base, потому что тип указателя - Base.
Но не понятно, почему A.call() вызывает метод f() класса Base, если объект A имеет тип Derived, в котором метод f() переопределен.
Вот пример, где вызывается именно метод класса Derived.
В моем примере написано: A.Call(); Который НАСЛЕДУЕТСЯ и НЕ ПЕРЕОПРЕДЕЛЯЕТСЯ.
Этот A.Call() и вызывает внутри себя базовый метод f(), который не виртуальный.
А если сделать f() виртуальным, то A.Call() будет вызывать f() по типу объекта А.
Chelioss
179 / 179 / 4
Регистрация: 08.01.2011
Сообщений: 1,131
10.11.2011, 22:35     Вопрос по наследованию #52
Цитата Сообщение от ValeryLaptev Посмотреть сообщение
В моем примере написано: A.Call(); Который НАСЛЕДУЕТСЯ и НЕ ПЕРЕОПРЕДЕЛЯЕТСЯ.
Call() нет, а f() переопределяется. Не совсем очевидно, почему вызывается f класса Base, если f переопределена.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
11.11.2011, 08:44     Вопрос по наследованию
Еще ссылки по теме:

C++ Написать простейшую программу по "перегрузке" и "наследованию"
Вопросы по наследованию C++

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

Или воспользуйтесь поиском по форуму:
ValeryLaptev
Эксперт C++
1004 / 783 / 46
Регистрация: 30.04.2011
Сообщений: 1,595
11.11.2011, 08:44     Вопрос по наследованию #53
Цитата Сообщение от Chelioss Посмотреть сообщение
Call() нет, а f() переопределяется. Не совсем очевидно, почему вызывается f класса Base, если f переопределена.
Вот это и есть самое важное в понимании виртуальных функций...
Потому как при трансляции базового класса компилятор НИФИГА не знает о наследниках. Поэтому НАМЕРТВО связывает CALL со своей f() ПРИ КОМПИЛЯЦИИ.

Если же мы пишем virtual, то это мы подсказываем компилятору: погоди намертво связывать, наследники будут. И компилятор формирует код, который связывает вызов ПРИ ВЫПОЛНЕНИИ программы...
Yandex
Объявления
11.11.2011, 08:44     Вопрос по наследованию
Ответ Создать тему
Опции темы

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