Собственно 2 вопроса
1. Насколько оправдано написание const спецификатора при передаче в метод параметров по значению? Может в этом нет смысла, ведь идет копирование?
2. Насколько хорошо возвращать ссылку на члены класса? Может быть история что ссылка осталась, а класса нет. Может лучше отдавать по значению?
Здравствуйте, yaser, Вы писали:
Y>Собственно 2 вопроса Y>1. Насколько оправдано написание const спецификатора при передаче в метод параметров по значению? Может в этом нет смысла, ведь идет копирование?
Константность значения параметра не входит в сигнатуру метода, так что смысла в этом столько же, сколько в константности локальных переменных метода.
Y>2. Насколько хорошо возвращать ссылку на члены класса? Может быть история что ссылка осталась, а класса нет. Может лучше отдавать по значению?
Если такая ситуация возможна, то плохо, если нет, то нет.
Здравствуйте, yaser, Вы писали:
Y>Добрый день.
Y>Есть класс
Y>class Drink { Y>private: Y> std::string m_name; Y>public: Y> std::string value(const std::string company, const int) const; Y> const std::string& name() const;
Y>}
Y>Собственно 2 вопроса Y>1. Насколько оправдано написание const спецификатора при передаче в метод параметров по значению? Может в этом нет смысла, ведь идет копирование?
Когда банально хочется быть уверенным что внутри функции параметр случайно не меняется.
Например, `double f(const double coef)`, если внутри функции решается какое-то уравнение с коэффициентами
и там есть вычисляемые переменные типа `coef2`, а придумать им более различимые имена напряжно,
то `const` переложит проверку на плечи компилятору.
Y>2. Насколько хорошо возвращать ссылку на члены класса? Может быть история что ссылка осталась, а класса нет. Может лучше отдавать по значению?
rust поможет переложить проверку на подобную ситацию на плечи компилятора, а в c++ либо скорость и самоконтроль, или копирование.
И в c++ std::string не может быть reference-counting поэтому по любому будет лишнее выделение памяти,
если строка большая.
Y>Собственно 2 вопроса Y>1. Насколько оправдано написание const спецификатора при передаче в метод параметров по значению? Может в этом нет смысла, ведь идет копирование?
Мне трудно представить себе ситуацию когда передача std::string по константному значению может быть оправдана. Если аргумент не меняется, то почему бы не передать его по константной ссылке и избежать возможного лишнего копирования? Y>2. Насколько хорошо возвращать ссылку на члены класса? Может быть история что ссылка осталась, а класса нет. Может лучше отдавать по значению?
Это зависит от контракта. Автор класса определяет контракт и устанавливает границы. Если контракт твоего класса подразумевает, что возвращаемое значение не может пережить сам объект (см. std::string::c_str), то все ОК.
DR>Константность значения параметра не входит в сигнатуру метода,так что смысла в этом столько же, сколько в константности локальных переменных метода.
DR>Если такая ситуация возможна, то плохо, если нет, то нет.
Здравствуйте, yaser, Вы писали:
Y>Собственно 2 вопроса Y>1. Насколько оправдано написание const спецификатора при передаче в метод параметров по значению? Может в этом нет смысла, ведь идет копирование?
Именно, нет смысла.
И ещё есть тонкость, что параметр типа std::string действительно константный, а параметр типа int может быть не-константным в другом объявлении.
В общем, лучше не надо.
Y>2. Насколько хорошо возвращать ссылку на члены класса? Может быть история что ссылка осталась, а класса нет. Может лучше отдавать по значению?
Ещё может быть такое, что значение, переданное по ссылке, поменялось внутри класса.
Так, для многопоточного использования в случае возврата по значению достаточно защитить все потенциально-многопоточные обращения к m_name мьютексом, при возврате по сслыке потокобезопасность добавить куда сложнее.
Здравствуйте, yaser, Вы писали:
Y>1. Насколько оправдано написание const спецификатора при передаче в метод параметров по значению? Может в этом нет смысла, ведь идет копирование?
Я обычно следую простым правилам:
1. Если аргумент внутри функции не модифицируется — пишу const.
2. Если аргумент типа класса — передаю по ссылке.
3. Если аргумент указатель и исходный объект не модифицируется — пишу const.
4. Если аргумент массив и исходные данные не модифицируются — пишу const указатель.
Y>2. Насколько хорошо возвращать ссылку на члены класса?
Возврат нестатическим методом класса ссылки на член класса — это норма. (Ц) Малышева .
В особенности если ссылка константная.
Бойся возврата указателя либо ссылки на локальный объект функции!
Вот там действительно подводные камни.
К счастью, обычно компилятор предупреждает об этом.
Y>Может быть история что ссылка осталась, а класса нет. Может лучше отдавать по значению?
Видимо, ты хотел сказать нет объекта класса?
Don't worry, be happy! (C) Bob Marley
Если нестатический метод класса вызывается от имени объекта класса, можно не переживать.
Вот если от имени указателя на несуществующий объект класса — тогда да, проблема.
1. По поводу передачи параметров с модификатором const по значению понял. +/- так думал, но хотел убедится в своих знаниях. Понятно что когда передаешь параметр по ссылке, то const имееть ОГРОМНОЕ значение.
2. Есть большой отдел разработчиков. Вы проектируете класс, не понятно кто, как, когда будет им пользоваться. Понятно, что если метод private, то для оптимизации взаимодействия внутренних метода класса вполне приемлимо возврат по const object_ref, но если метод паблик — не понятно как разработчик воспользуется возможностями. Может не стоит проектировать класс (в общем случае) публичные методы которого возвращают const object_ref?
Здравствуйте, yaser, Вы писали:
Y>2. Есть большой отдел разработчиков. Вы проектируете класс, не понятно кто, как, когда будет им пользоваться. Понятно, что если метод private, то для оптимизации взаимодействия внутренних метода класса вполне приемлимо возврат по const object_ref, но если метод паблик — не понятно как разработчик воспользуется возможностями. Может не стоит проектировать класс (в общем случае) публичные методы которого возвращают const object_ref?
Бро, я же писал тебе выше: это норма.
Ничего здесь опасного нет.
Вот навскидку простенький пример:
В комментариях специально поставил пояснения, какие именно методы get() вызываются.
Так что смело возвращай ссылки на члены класса и пой:
Don't worry! Be happy!
Z>Когда банально хочется быть уверенным что внутри функции параметр случайно не меняется. Z>Например, `double f(const double coef)`, если внутри функции решается какое-то уравнение с коэффициентами Z>и там есть вычисляемые переменные типа `coef2`, а придумать им более различимые имена напряжно, Z>то `const` переложит проверку на плечи компилятору.
Нет смысла в этом случае передавать по значению.
Вполне по константной ссылке делает то же самое — запрещает изменять параметр внутри.
Не только посредством присваивания, но и посредством ввода извне.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Оно, конечно, сам-себе буратино, но факт остается фактом — возвращать по значению — безопасней.
ps/
И да, указатель не является необходимым условием. Можено передать ссылку на шашку в конструктор другого класса, экземпляр которого будет возвращен из функции по значению, при этом, естествено, ящик и шашка, на которую есть ссылка, будут разрушены по выходу из этой функции.
Здравствуйте, LaptevVV, Вы писали:
Z>>Когда банально хочется быть уверенным что внутри функции параметр случайно не меняется. Z>>Например, `double f(const double coef)`, если внутри функции решается какое-то уравнение с коэффициентами Z>>и там есть вычисляемые переменные типа `coef2`, а придумать им более различимые имена напряжно, Z>>то `const` переложит проверку на плечи компилятору. LVV>Нет смысла в этом случае передавать по значению. LVV>Вполне по константной ссылке делает то же самое — запрещает изменять параметр внутри.
Не совсем. Есть ещё важное отличие — код без ссылки может работать быстрее. Выше приведён пример с решением уравнения, я же приведу пример ещё проще: умножение вектора на число:
void mul_const_ref(float a[], size_t n, const float& factor) {
for (size_t i = 0; i < n * 4; ++i)
a[i] *= factor;
}
void mul_const_value(float a[], size_t n, const float factor) {
for (size_t i = 0; i < n * 4; ++i)
a[i] *= factor;
}
Такой код обычен и должен отлично векторизоваться даже не очень современными версиями компиляторов. В нём только n * 4 добавлено для удобства, чтобы не загромождать рассмотрение случаями, когда почти весть массив обрабатывается векторно, но остаток — скалярно.
Смотрим на результат: https://godbolt.org/g/1No0ev
Функция mul_const_value использует инструкции векторного умножения — тут всё более-менее хорошо.
Функция mul_const_ref же не только не векторизовалась, но и делает нечто странное — на каждой из итераций загружает factor из памяти заново!
В общем, даже с простой задачей умножения вектора на константу вышло фиаско — передача аргумента по константной ссылке всё портит.
Почему так происходит? Потому что в С++ нет ключевого слова restrict или аналога для ссылок и указателей. То есть компилятор не может гарантировать, что на очередной итерации присваивание a[i] не изменит значение factor. Поэтому он и вынужден на каждой итерации перечитывать это значение из памяти — а вдруг оно изменилось. Ведь менять значение объекта, на которое указывает константная ссылка, не запрещено в стандарте.
Впрочем, некоторые компиляторы вставляют в начало функции несколько проверок на то, что диапазон памяти, занимаемый массивом a[0:n*4], не пересекается с памятью, занимаемой factor. И в зависимости от результата переходят на векторную или на скалярную версию. Так не теряется возможность векторизовать цикл, но из-за дополнительных проверок и из-за дополнительного кода, такие функции получаются большими по размеру, а работают всё равно чуть медленнее, чем если бы мы сразу передали factor по значению.
Здравствуйте, tstalker, Вы писали:
T>Здравствуйте, yaser, Вы писали:
Y>>2. Есть большой отдел разработчиков. Вы проектируете класс, не понятно кто, как, когда будет им пользоваться. Понятно, что если метод private, то для оптимизации взаимодействия внутренних метода класса вполне приемлимо возврат по const object_ref, но если метод паблик — не понятно как разработчик воспользуется возможностями. Может не стоит проектировать класс (в общем случае) публичные методы которого возвращают const object_ref?
T>Бро, я же писал тебе выше: это норма. T>Ничего здесь опасного нет. T>Вот навскидку простенький пример: T>
T>В комментариях специально поставил пояснения, какие именно методы get() вызываются. T>Так что смело возвращай ссылки на члены класса и пой:
А если так:
Здравствуйте, tstalker, Вы писали:
T>Защитить данные от подобного варварства помогут умные указатели:
int main(void)
{
std::unique_ptr<C> p(new C("abcde"));
const std::string& s(p->get());
p.reset(new C("fghij")); // пой вместе со мной, сестра, и танцуй, ведь это индийское кино
std::cout << s << std::endl;
}
D>int main(void)
D>{
D> std::unique_ptr<C> p(new C("abcde"));
D> const std::string& s(p->get());
D> p.reset(new C("fghij")); // пой вместе со мной, сестра, и танцуй, ведь это индийское кино
D> std::cout << s << std::endl;
D>}
D>
А если серьёзно, то таки да — встроенные ссылки и указатели запросто могут потерять актуальность.
Кроме того, механизм встроенных ссылок и указателей слабо взаимодействует с умными указателями и не синхронизируется автоматически.
А потому — внимательность, внимательность и ещё раз внимательность.
Здравствуйте, yaser, Вы писали: Y>1. Насколько оправдано написание const спецификатора при передаче в метод параметров по значению? Может в этом нет смысла, ведь идет копирование?
а в чем смысл передачи по значению тут? надо по const &. это, конечно, про string. const int никогда не встречал. не, вру, однажды — знакомый прочитал книгу GPU gems, что, мол, надо везде передавать по const & и стал везде писать const int &x.
единственная причина писать параметр тут const int — если есть член класса с таким же именем и не хочется перепутать внутри метода при записи значения. но это не совсем нормальный подход.
Y>2. Насколько хорошо возвращать ссылку на члены класса? Может быть история что ссылка осталась, а класса нет. Может лучше отдавать по значению?
обычно по значению отдают. бывает, что есть метод типа const &data() const который возвращает ссылку на внутренний буфер, если нужно по какой-то причине. в остальных случаях лучше по значению
D>Оно, конечно, сам-себе буратино, но факт остается фактом — возвращать по значению — безопасней. D>ps/
Провал тут случился в тот момент, когда ты решил хранить ссылку, а не копию, в коде, который что-то рушит. Никто не заставлял тебя хранить ссылку, а не копию...
Когда из метода доступа возвращают ссылку, а не копию, то решение о том, что хранить отдают наружу просто.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, __kot2, Вы писали:
__>обычно по значению отдают. бывает, что есть метод типа const &data() const который возвращает ссылку на внутренний буфер, если нужно по какой-то причине. в остальных случаях лучше по значению
Зачем? Всё равно же решение хранить копию или ссылку принимают снаружи?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, __kot2, Вы писали:
Y>>1. Насколько оправдано написание const спецификатора при передаче в метод параметров по значению? Может в этом нет смысла, ведь идет копирование? __>а в чем смысл передачи по значению тут? надо по const &. это, конечно, про string.
Согласно "последнему постановлению ВЦСПС" std::string надо передавать по значению (и без const) в том случае, если внутри функции эту строку подлежит сохранить в другую переменную, например, в член класса:
Здравствуйте, B0FEE664, Вы писали:
BFE>Здравствуйте, __kot2, Вы писали:
Y>>>1. Насколько оправдано написание const спецификатора при передаче в метод параметров по значению? Может в этом нет смысла, ведь идет копирование? __>>а в чем смысл передачи по значению тут? надо по const &. это, конечно, про string.
BFE>Согласно "последнему постановлению ВЦСПС" std::string надо передавать по значению (и без const) в том случае, если внутри функции эту строку подлежит сохранить в другую переменную, например, в член класса:
BFE>
Здравствуйте, _hum_, Вы писали:
BFE>>Согласно "последнему постановлению ВЦСПС" std::string надо передавать по значению (и без const) в том случае, если внутри функции эту строку подлежит сохранить в другую переменную, например, в член класса:
BFE>>
__>странно, ведь все равно ж strName в стек будет засунут. или надо рассчитывать на оптимизацию компилятора?
Да, можно рассчитывать, так как функция — inline, но дело тут не в этом, а в том, что у std::string есть часть лежащая в хипе, которую так или иначе надо скопировать один раз. Если есть вызов типа такого:
, то для константной ссылки будет два копирования, а для вышеприведённой функции — одно. Однако же, если копирование значения параметра внутри функции не нужно, то, теоретически, выгодно передавать константную ссылку, но при этом стоит учесть это
Здравствуйте, B0FEE664, Вы писали:
BFE>Здравствуйте, _hum_, Вы писали:
BFE>>>Согласно "последнему постановлению ВЦСПС" std::string надо передавать по значению (и без const) в том случае, если внутри функции эту строку подлежит сохранить в другую переменную, например, в член класса:
BFE>>>
__>>странно, ведь все равно ж strName в стек будет засунут. или надо рассчитывать на оптимизацию компилятора? BFE>Да, можно рассчитывать, так как функция — inline, но дело тут не в этом, а в том, что у std::string есть часть лежащая в хипе, которую так или иначе надо скопировать один раз. Если есть вызов типа такого: BFE>
Здравствуйте, yaser, Вы писали:
Y>Собственно 2 вопроса Y>1. Насколько оправдано написание const спецификатора при передаче в метод параметров по значению? Может в этом нет смысла, ведь идет копирование?
По поводу этого пункта уже выше все детально разобрали.
Y>2. Насколько хорошо возвращать ссылку на члены класса? Может быть история что ссылка осталась, а класса нет. Может лучше отдавать по значению?
Плохо. На практике так делать не стоит, если только профайлер не показал что здесь узкое место. С точки зрения дизайна, это, почти, нарушение инкапсуляции, т.к. говорит что где-то там, внутри, есть std::string. Если время жизни класса планируется долгим, то при его дальнейшей модификации, возврат по ссылке может привести к проблемам с реализацией. Особенно осторожно нужно относиться к возвратам по ссылке, если метод виртуальный и класс планирует быть базовым для других или входить в иерархию наследования.
Здравствуйте, _hum_, Вы писали:
BFE>>Да, можно рассчитывать, так как функция — inline, но дело тут не в этом, а в том, что у std::string есть часть лежащая в хипе, которую так или иначе надо скопировать один раз. Если есть вызов типа такого: BFE>>
__>?
Первый в конструкторе std::string, в strName;
второй при присваивании в m_name.
__>А еще впорос — для случая передачи по константному значению компилятор сможет выполнить оптимизацию и не копировать это константное значение в стек? __>
Здравствуйте, Erop, Вы писали: E>Зачем? Всё равно же решение хранить копию или ссылку принимают снаружи?
ну вот допустим у нас есть ф-ия конкатенации строк
у нас есть два варианта
ф-ия
string plus(const string &a, const string &b) — которая создает новую строку и возвращает ее
string &plus(string &a, const string &b) — которая модифицирует a и возвращает а
первый вариант ведет себя более ожидаемо, можно просто по запаре не заметить, что второй модифицирует a, второй — сильно быстрее на большом кол-ве таких операций
как бы идеологически удобнее именно первый вариант. мы не модифицируем обьект, а создаем новый. по крайней мере это даже потокобезопасно.
так и куче ф-ий идеологически правильнее будет сконструирвать какой-то временный обьект и вернуть его. но в этом случае нам, сообв-но нельзя хранить его по ссылке.
бывает, что нам реально нужны указатели на обьекты, а не копии
типа string &find(...)
но в этом случае я лично предпочитаю не мучаться раздумиями о владениях и временах жизни обьектов и не мучать этим коллег, а перейти к смартпойнтерам вместо референсов, что избавит от ненужных копирований обьектов, и при этом сами смартпойнтеры, конечно, возвращатся по значению
string_ptr find(...)
Здравствуйте, __kot2, Вы писали:
__>string plus(const string &a, const string &b) — которая создает новую строку и возвращает ее __>string &plus(string &a, const string &b) — которая модифицирует a и возвращает а
__>первый вариант ведет себя более ожидаемо, можно просто по запаре не заметить, что второй модифицирует a, второй — сильно быстрее на большом кол-ве таких операций __>как бы идеологически удобнее именно первый вариант. мы не модифицируем обьект, а создаем новый. по крайней мере это даже потокобезопасно.
1) Это вопрос не про то, что возвращать, а про то, что менять.
2) второе очень популярно, просто обычно эту фнкцию называют operator+=
__>так и куче ф-ий идеологически правильнее будет сконструирвать какой-то временный обьект и вернуть его. но в этом случае нам, сообв-но нельзя хранить его по ссылке.
Нет, когда мы возвращаем НОВЫЙ объект, то выбора как возвращать нет.
Вопрос стоит только тогда, когда мы можем выбрать что возвращать, ссылку или копию...
скажем так:
template<typename T>
T& select( bool takeLeft, T& left, T& right ) { return takeLeft ? left : right; }
__>но в этом случае я лично предпочитаю не мучаться раздумиями о владениях и временах жизни обьектов и не мучать этим коллег, а перейти к смартпойнтерам вместо референсов, что избавит от ненужных копирований обьектов, и при этом сами смартпойнтеры, конечно, возвращатся по значению
То есть какой-нибудь метод GetName у тебя возвращает смартпоинтер на строку?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали: E>1) Это вопрос не про то, что возвращать, а про то, что менять. E>2) второе очень популярно, просто обычно эту фнкцию называют operator+=
я просто пример показал двух разных поведений. когда у нас результат — во временном обьекте. или мы результат можем и на месте организовать
E>То есть какой-нибудь метод GetName у тебя возвращает смартпоинтер на строку?
я вообще не люблю геттеры-сеттеры. использую только если прямо ну никак нельзя без них
поэтому вместо сеттера у меня скорее всего будет создание нового обьекта
типа вместо
void marry(husband, wife)
{
wife.set_last_name(husband.last_name)
}
будет что-то в духе
Person married_wife(husband, wife)
{
return person(wife.first_name, husband.last_name)
}
а вместо геттеров я предпочитаю иметь иммутабельные поля (или в С++ const ссылки-указатели на обьекты) и спокойно не парясь обращаться к ним напрямую
Здравствуйте, __kot2, Вы писали:
__>я просто пример показал двух разных поведений. когда у нас результат — во временном обьекте. или мы результат можем и на месте организовать
Тем не менее, operator+ и operator+= обычно считаются РАЗНЫМИ функциями...
E>>То есть какой-нибудь метод GetName у тебя возвращает смартпоинтер на строку? __>я вообще не люблю геттеры-сеттеры. использую только если прямо ну никак нельзя без них
Ну, вот, например CFile::GetName что должен возвращать? Смартпоинтер на строку?
__>а вместо геттеров я предпочитаю иметь иммутабельные поля (или в С++ const ссылки-указатели на обьекты) и спокойно не парясь обращаться к ним напрямую
__>const Person &wife;
__>cout << wife.last_name << endl; — нормалек
IMHO, это не всегда удобно, ну и сильно выходит за тему что возвращать...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали: E>Тем не менее, operator+ и operator+= обычно считаются РАЗНЫМИ функциями...
да кто же спорит. но не будете же вы для всего писать два варианта — на месте и с созданием копии.
типа, например, реверс строки. вы всегда можете с помощью += реализовать + и наоборот (обычно первое), но не будете же вы везде дублировать одни и те же ф-ии.
проще писать и подерживать код, который обьекты не модифицирует никогда. в этом и есть смысл фукнционального программирования. но совсем не обязательно писать на хаскеле, чтобы пользоваться плюшками такого подхода
E>Ну, вот, например CFile::GetName что должен возвращать? Смартпоинтер на строку?
вообще такого метода у файла быть не должно
__>>а вместо геттеров я предпочитаю иметь иммутабельные поля (или в С++ const ссылки-указатели на обьекты) и спокойно не парясь обращаться к ним напрямую __>>const Person &wife; __>>cout << wife.last_name << endl; — нормалек E>IMHO, это не всегда удобно, ну и сильно выходит за тему что возвращать...
когда я давно начинал писать я писал миллионами эти геттеры. потом задолбался. это просто лишняя работа, не несущая никаких бенефитов. переделать доступ к члену на обращение к геттеру — фигня вопрос. конечно, не для каких-нибудь публичных библиотек, но я их никогда и не писал
Здравствуйте, __kot2, Вы писали:
__>проще писать и подерживать код, который обьекты не модифицирует никогда. в этом и есть смысл фукнционального программирования. но совсем не обязательно писать на хаскеле, чтобы пользоваться плюшками такого подхода
На С++ сильно не все программы в функциональном стиле пишутся...
Ну и часто дорого просто... Ну, например функциональная версия CART насколько дороже будет по памяти?
E>>Ну, вот, например CFile::GetName что должен возвращать? Смартпоинтер на строку? __>вообще такого метода у файла быть не должно
Почему?
__>когда я давно начинал писать я писал миллионами эти геттеры. потом задолбался. это просто лишняя работа, не несущая никаких бенефитов. переделать доступ к члену на обращение к геттеру — фигня вопрос. конечно, не для каких-нибудь публичных библиотек, но я их никогда и не писал
Ну я тоже гетеры не люблю. Но есть же нетривиальные гетеры...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали: __>>проще писать и подерживать код, который обьекты не модифицирует никогда. в этом и есть смысл фукнционального программирования. но совсем не обязательно писать на хаскеле, чтобы пользоваться плюшками такого подхода E>На С++ сильно не все программы в функциональном стиле пишутся... E>Ну и часто дорого просто... Ну, например функциональная версия CART насколько дороже будет по памяти?
разумеется, допустим, нейросеть в ф-ом стиле написанная вообще никому не нужна будет
поэтому на ф-ых языках никто сильно и не пишет. просто в большинстве случаев, типа простейшей работы с юзерами, бд, удобнее когда код в ф-ом стиле.
вместо
user.set_name(new_name)
{
validate()
commit()
notify()
}
new_user = new user(new_name, old_age) или new_user = new user(old_name, new_age)
и controller.replace(old_user, new_user)
который уже будет делать
{
validate()
commit()
notify()
}
E>>>Ну, вот, например CFile::GetName что должен возвращать? Смартпоинтер на строку? __>>вообще такого метода у файла быть не должно E>Почему?
скорее вопрос стоит — а зачем он там нужен?
может ли имя файла измениться за время открытия файла?
бывают ли файлы безымянные?
а нет ли ньюансов с симлинками?
а нет ли случаев когда это имя укоротится до формата 8.3 для совместимости с чем-то? или юникодные символы не заменятся чем-то?
я вот лично просто не знаю ответов на эти вопросы, но подозреваю, что там скрываются тонны геморроя. и ради чего это? мы что, не знаем какой файл открываем при его открытии? зачем нам об этом задним числом узнавать?
E>Ну я тоже гетеры не люблю. Но есть же нетривиальные гетеры...
бывают еще и констукторы-деструкторы непритивиальные, который в логи пишут, уникальные id генерируют или еще какие сайд-эффекты. именно поэтому проще иметь смартпойнтер во многих случаях. так и пришли люди к java — C#. хотя никто не мешает в том же стиле писать на С++
Здравствуйте, __kot2, Вы писали:
__>поэтому на ф-ых языках никто сильно и не пишет. просто в большинстве случаев, типа простейшей работы с юзерами, бд, удобнее когда код в ф-ом стиле.
Ну это от области оч. зависит. Если перфомансом занята БД, то не ясно на кой вообще вокруг с С++ прыгать...
__>new_user = new user(new_name, old_age) или new_user = new user(old_name, new_age)
А если аттрибутов юзера примерно 100500, и они имеют свойство добавляться иногда?
E>>Почему? __>скорее вопрос стоит — а зачем он там нужен? __>я вот лично просто не знаю ответов на эти вопросы, но подозреваю, что там скрываются тонны геморроя. и ради чего это? мы что, не знаем какой файл открываем при его открытии? зачем нам об этом задним числом узнавать?
Ну, например, читаем мы из файла данные, и тут находим ошибку, хотим кинуть исключение с диагностикой, как его параметризовать указанием на то, в каком конкретно файле ошибка?
E>>Ну я тоже гетеры не люблю. Но есть же нетривиальные гетеры... __>бывают еще и констукторы-деструкторы непритивиальные,
Это ты про другое... Например, бывают виртуальные функции GetЧегоНибудь...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали: E>А если аттрибутов юзера примерно 100500, и они имеют свойство добавляться иногда?
сгруппировать в отдельные классы, коих будет опять же, только несколько. наверное еще какие-то варианты есть.
E>Ну, например, читаем мы из файла данные, и тут находим ошибку, хотим кинуть исключение с диагностикой, как его параметризовать указанием на то, в каком конкретно файле ошибка?
это если мы exit() хотим сделать на месте, хотелось бы всю инфу протащить. а так файл же сам по себе не бывает, есть обвязка, которая знает что это за файл и обрабатывает разные ситуации. надо просто кинуть исключение наверх, что прочитать не можем, а уж что не можем — знают наверну
E>>>Ну я тоже гетеры не люблю. Но есть же нетривиальные гетеры... __>>бывают еще и констукторы-деструкторы непритивиальные, E>Это ты про другое... Например, бывают виртуальные функции GetЧегоНибудь...
бывает. убрать поле в приватные, заменить обращение к полю на вызов ф-ии в тех местах, где это происходит — не вижу никаких проблем
Здравствуйте, __kot2, Вы писали:
__>это если мы exit() хотим сделать на месте, хотелось бы всю инфу протащить. а так файл же сам по себе не бывает, есть обвязка, которая знает что это за файл и обрабатывает разные ситуации. надо просто кинуть исключение наверх, что прочитать не можем, а уж что не можем — знают наверну
Это же неудобно. Вот прикинь, я дал команду "открыть базу данных", а она в ответ плюётся исключением "повреждён файл такой-то". Так удобно. А если мне везде по стеку надо исключения обрабатывать и переформатировать, то я точно где-то ошибусь, это трудно тестировать и это всё точно лишняя работа. Намного лучше уметь у файла спросить имя...
Тем более, что это не проблема...
__>бывает. убрать поле в приватные, заменить обращение к полю на вызов ф-ии в тех местах, где это происходит — не вижу никаких проблем
Если не помнишь, мы обсуждаем что возвращать: копию или ссылку
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали: E>Это же неудобно. Вот прикинь, я дал команду "открыть базу данных", а она в ответ плюётся исключением "повреждён файл такой-то". Так удобно. А если мне везде по стеку надо исключения обрабатывать и переформатировать, то я точно где-то ошибусь, это трудно тестировать и это всё точно лишняя работа. Намного лучше уметь у файла спросить имя... E>Тем более, что это не проблема...
я даже псевдокод этого представить не могу
типа
open_db("filename")
и ... что, хочется чтобы что?
__>>бывает. убрать поле в приватные, заменить обращение к полю на вызов ф-ии в тех местах, где это происходит — не вижу никаких проблем E>Если не помнишь, мы обсуждаем что возвращать: копию или ссылку
копию. если обьект большой и есть шанс просаживания скорости из-за лишних копирований — смартпойнтер на него.