Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 17.01.2012, 18:35   #1
soirkar
Пользователь
 
Регистрация: 21.06.2011
Сообщений: 13
По умолчанию Матрица. Перегрузка операторов

Код:
matrix& matrix :: operator *= (const matrix& x1) 
{
	if( СhM(x1) ) //СhM - проверка на возможность умножения двух матриц
	{
		*this=this*x1;
	} 
	
	else throw "ERROR"; 
	return *this;
}
Написал следующее, каким еще способом можно перегрузить оператор *= и почему первый наиболее эффективный?
soirkar вне форума Ответить с цитированием
Старый 17.01.2012, 18:48   #2
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от soirkar Посмотреть сообщение
каким еще способом можно перегрузить оператор *= и почему первый наиболее эффективный?
1. В виде глобальной функции.
2. По каким критериям определяется "эффективность" способа перегрузки, в контексте вопроса?
_Bers вне форума Ответить с цитированием
Старый 17.01.2012, 18:55   #3
soirkar
Пользователь
 
Регистрация: 21.06.2011
Сообщений: 13
По умолчанию

_Bers, количество вызываемых конструкторов/деструкторов.
То, что в виде глобальной функции я итак понял, я не знаю как это реализовать, совсем.

Последний раз редактировалось soirkar; 17.01.2012 в 18:59.
soirkar вне форума Ответить с цитированием
Старый 17.01.2012, 18:59   #4
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от soirkar Посмотреть сообщение
_Bers, количество вызываемых конструкторов/деструкторов.
В таком случае, эффективность корректно сконструировано глобальной функции ничуть не уступает по эффективности корректно сконструированному мемберу класса.

/ps а вот идея выбрасывать исключение в случае не_валидности входных данных - не самая удачная. Ибо: нарушение инкапсуляции и инварианта класса.

К тому же - не_рациональное падение производительности.
_Bers вне форума Ответить с цитированием
Старый 18.01.2012, 20:19   #5
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Цитата:
/ps а вот идея выбрасывать исключение в случае не_валидности входных данных - не самая удачная. Ибо: нарушение инкапсуляции и инварианта класса.
интересно чем это искючения нарушают чтото?
безопасный код не в моде?

просто стоит или завести класс исключений, или же документировать бросаемые исключение.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 18.01.2012, 21:12   #6
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
интересно чем это искючения нарушают чтото?
безопасный код не в моде?

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

1. Инкапсуляция гарантирует, что пользователи класса смогут пользоваться его услугами ничего не зная о деталях реализации этого класса

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

То есть, для безопасной работы с таким классом, пользователям этого класса придётся ознакомится с деталями реализации этого класса.
Итого - инкапсуляция нарушена.

2. Инвариант класса гарантирует стабильную и безотказную работу в случае, если пользователь работает с классом посредством его публичного интерфейса.

Это означает, что какие бы аргументы пользователь не запихивал в паблик методы класса, класс обязан проверить входящие данные, и корректно их обработать. В том числе корректно отреагировать, если входящие данные, которые оказались не_валидными. Класс не должен допустить крэш по своей вине.

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

Итого - нарушение инварианта класса.

А теперь самое главное: для чего нужны исключения? Какова область их применения?

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

Что такое исключительная ситуация? Это ошибка, приводящая к отказу системы, которую сам по себе класс спрогнозировать не в состоянии.

То есть, проверить входные данные, и определить что данные не_валидные - класс вполне себе может. И отреагировать так, что бы при этом система осталась на плаву - тоже вполне себе может.
Проверка входящих данных - штатная работа класса, и к исключительным ситуациям отношения не имеет.

Примером исключительной ситуации может быть, например исключение брошенное оператором new.

Не удалось выделить память. Это исключительная ситуация. Контейнер самостоятельно не в состоянии определить заранее, бросит ли new исключение, или нет. Он выделяет память, и ловит исключение на случай аварии. И соответственно реагирует.

Исключение должны отлавливать и реагировать на них сами же классы внутри себя (снаружи никто ничего не знает - инкапсуляция).
И только если совсем все плохо, и ситуация такова, что класс самостоятельно разрулить возникшую проблему не в состоянии - только тогда, исключение уходит за пределы класса, в надежде что вызывающая сторона что-то сможет сделать, и спасти систему от крэша.

Чем дальше исключение улетело от источника аварии, тем ниже вероятность, что аварию удастся предотвратить.

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

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

То есть, вместо того, что бы облегчать труд пользователей класса, он наоборот, спихивает все на них. Это архитектурный фейл. Ну и нафига вообще нужен класс, который не облегчает труд программиста?

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

Последний раз редактировалось _Bers; 18.01.2012 в 21:32.
_Bers вне форума Ответить с цитированием
Старый 18.01.2012, 21:57   #7
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Цитата:
1. Инкапсуляция гарантирует, что пользователи класса смогут пользоваться его услугами класса ничего не зная о деталях реализации этого класса

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

То есть, для безопасной работы с таким классом, пользователям этого класса придётся ознакомится с деталями реализации этого класса.
Итого - инкапсуляция нарушена.
скажите это разработчикам C# и Java.
у обоих строгое ООП.
у второго можно указать список бросаемых исключений которые вызывающий обязан обработать.

существует документация, в которой должно быть все указано.
а насчет знать содержимое класса для анализа это бред, не нужно это, главное знать что и почему, это задача документации.
Цитата:
2. Инвариант класса гарантирует стабильную и безотказную работу в случае, если пользователь работает с классом посредством его публичного интерфейса.
как раз-таки исключения тут вполне, это вместо вечных флагов результата, и особых значений результата.

исключение это уведомление о попытке нарушить целостность класса.
и уж куда лучше кинуть исключение с обьяснением причины вылета, чем просто вернуть false и пусть сами разбираються что там не так.
Цитата:
Исключения нужны для того, что бы спасти работоспособность системы при возникновении исключительных ситуаций
чуть больше берите.
почему вы считаете что каждое исключение может быть обработано только в main?
при вложенности классов(1 использует 2) каждое исключение должно быть по максимуму обработано(но не в ущерб) по зависимости классов.
Цитата:
Что такое исключительная ситуация? Это ошибка, приводящая к отказу системы, которую сам по себе класс спрогнозировать не в состоянии.
нет, это ситуация в которой класс не способен работать корректно, не важно, может ли он точно назвать причину или нет.
а вот насчет исправления тут иначе, если класс может исправить ситуацию без потерь, то можно не кидать исключение.
Цитата:
Класс, который бросает исключение по поводу и без повода (это у него типа штатная работа такая, чуть что - бросаем исключение, и пусть вызывающая сторона разгребает) - мало того, что не_инваринтен, и нарушает инкапсуляцию, а он в принципе спихивает всю ответственность за собственную работоспособность на вызывающую сторону.
ничего он не нарушает.
документация должна быть у хороших классов.
и так же например реализовать исключения наследуюясь от одного определенного класса(например от std::exception)

понимаю, не принято так в С++.
просто я с других ЯП(Delphi,C#,Java), где исключения бросаються именно по делу, привык к ним.
(и там принято их обрабатывать, особенно в Java, где вы обязаны это делать)

нужно четко знать, где бросать исключение, а где нет.
например для класса Integer в методе FromString если строка имеет неверный формат, вполне нормально бросить исключение.
а вот для метода FromStringDef это уже недопустимо.

но опять же в С++, когда порою бывает по кучи классов строк, то есть нету стандарта на исключения, тут с этим тяжело к сожалению.
а так бы было бы хорошо.
Цитата:
То есть, вместо того, что бы облегчать труд пользователей класса, он наоборот, спихивает все на них. Это архитектурный фейл. Ну и нафига вообще нужен класс, который не облегчает труд программиста?
то есть обработать так как хочет автор класса, а не так как хочет пользователь класса это лучше?
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 18.01.2012, 22:24   #8
Rififi
Старожил
 
Регистрация: 19.08.2009
Сообщений: 2,119
По умолчанию

_Bers

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

Неправильно. Выбрасываемые исключения описываются в документации, а в некоторых случаях - и на декларативном уровне.


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

исключения C++ имеют весьма отдаленное отношение к исключительным ситуациям


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

То есть, вместо того, что бы облегчать труд пользователей класса, он наоборот, спихивает все на них. Это архитектурный фейл. Ну и нафига вообще нужен класс, который не облегчает труд программиста?


Исключения заставляют программиста более сурьезно относится к кодированию. Если типичный быдло-программер не проверяет кодов возврата и сбой может обнаружиться через продолжительное время и нанести значительный ущерб, то "забить" на исключение уже не получится. Ему по-любому придется либо повышать свой уровень и качество кода. либо переквалифицироваться дворники.
Rififi вне форума Ответить с цитированием
Старый 18.01.2012, 22:26   #9
netrino
Участник клуба
 
Аватар для netrino
 
Регистрация: 15.07.2008
Сообщений: 1,933
По умолчанию

soirkar, реализовывать оператор умножение как присваивающий (*=) эффективней, потому что, в ряде случаев, можно обойтись без лишних выделений памяти.
_Bers, в очередной раз не согласен с Вами. Исключения, бросаемые классом(ф-цией) - это тоже часть публичного интерфейса класса. Безусловно, согласен в том, что нужно минимизировать их использование и избегать такого обилия исключений как в Java, но в допустимых пределах исключения весьма удобны. Инвариант класса даёт гарантию пребывать в корректном состоянии, пока он доступен для использования, но что делать, если по каким-то причинам он перешёл или перейдёт в некорректное состояние после следующего действия?
С моей точки зрения, вполне оправданно использование исключения в данном случае, правда швырять строку, конечно же не стоило, надо было воспользоваться std::invalid_argument из stdexcept
netrino вне форума Ответить с цитированием
Старый 18.01.2012, 23:13   #10
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение

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

Исключительная ситуация, это аварийная ситуация, предупредить которую класс сам не в состоянии.

Исключение - это сигнал об ошибке, который нельзя проигнорировать.


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

Тогда возникает закономерный вопрос: почему вызывающая сторона обязана реагировать на все сигналы класса?

О чем таком ужасном может поведать класс, что это нельзя никак проигнорировать?

Класс не может знать о вызывающей стороне. Он несет ответственность только за личную работоспособность.

Как он может знать, что является фатальным для вызывающей стороны, а что нет?

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
исключение это уведомление о попытке нарушить целостность класса.
Аргумент пришёл не_валидный? Ну и как это может повредить целостности класса? Он что, не в состоянии отличить валидный аргумент от не_валидного? А если в состоянии, стало быть уже ему аргументы входящие никак навредить не могут.

Что, сразу панику то поднимать? Может быть так задумано, что некоторые аргументы могут быть не_валидными?

Класс не знает природу вызывающей стороны, и не может судить о её корректности её действий.

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
и уж куда лучше кинуть исключение с обьяснением причины вылета, чем
просто вернуть false и пусть сами разбираються что там не так.
Не должно быть никаких вылетов. Класс пофиксил, что с данными аргументами работать не может, и сигналит об этом вызывающей стороне.
Вызывающая сторона что хочет, то и делает. Класса это не касается.

Класс не должен заставлять вызывающую сторону реагировать на все его сигналы, за исключением сигналов, которые нельзя проигнорировать
Другими словами, за исключением возникновения исключительных ситуаций.

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
почему вы считаете что каждое исключение может быть обработано только в main?
Я ни слова не говорил ни о каком main.
Речь идет от отношениях "вызывающая сторона - поставщик услуг".
Поставщик услуг выполняет свою штатную работу, и сигналит о состоянии проделанной работы. Его не интересует зачем он что-то делает, и что с результатами его работы будут делать дальше. Его задача - делать свою работу, и не допустить крэша по собственной вине. В случае возникновения исключительной ситуации, он либо справляется с трудностями самостоятельно, либо исключения уходят дальше - к вызывающей стороне, в надежде, что там смогут справится.

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
то есть обработать так как хочет автор класса, а не так как хочет пользователь класса это лучше?
Не надо передёргивать ответственность. Класс сам по себе не знает где он будет использоваться. Он знает только как он сам устроен, и как он сам работает. И все. Он не знает, какие из его сигналов принципиально важны для вызывающей стороны, а какие нет.
Он так же ничего не знает о том, какие реакции для каких его сигналов предусмотрены вызывающей стороной. И как именно, она хочет их обрабатывать.


Допустим, есть функция Err StringToInt(const std::string& crc, int& dst);

Получает на вход строку, и возвращает число.
Строка должна содержать символьное представление числа, иначе...

Иначе что? Система обрушится, или как?
Как функция в сферическом вакууме может знать, является ли данная ситуация угрозой для функционирования системы?

Почему она заставляет вызывающую сторону отлавливать исключение?
Почему из-за каждого пшика нужно уродовать код бесчисленным количеством ловушек?

Теперь второй вопрос: если ситуация, когда на входе оказалась кривая строка - реально является угрозой для системы, стало быть это ошибка программиста?

Как вообще в таком случае могло получится так, что на входе оказалась кривая строка?

А если это реально ошибка программиста, ну поймает её ловушка исключений, и чего? Каким таким образом прикажете ловушкам исключений исправлять ошибки самого программиста?

Объясните мне смысл брошенного исключения данной функцией, в случае не_валидной строки?
_Bers вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Перегрузка операторов C++ applegrub Общие вопросы C/C++ 4 20.12.2011 01:04
Перегрузка операторов stas135642 Общие вопросы C/C++ 0 13.11.2011 23:09
С++,перегрузка операторов colesik Помощь студентам 0 23.12.2010 23:07
Перегрузка операторов(С++) Сергей AfeR Помощь студентам 0 16.06.2010 18:34
Перегрузка операторов, Организация перегрузки операторов chagin_yav Помощь студентам 2 12.05.2008 09:15