LINUX.ORG.RU

[C++] code style

 


0

1

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

Читаю сижу code style guide по плюсам и вижу там следующее:

11. Private class variables should have underscore suffix.

A side effect of the underscore naming convention is that it nicely resolves the problem of finding reasonable variable names for setter methods and constructors:

void setDepth (int depth) { depth_ = depth; }

У меня возник только один вопрос - а что, this уже не рулит?

★★

У меня возник только один вопрос - а что, this уже не рулит?

this - это хорошо, но с underscore ты сразу видишь приватные переменные класса

shty ★★★★★
()
Ответ на: комментарий от PolarFox

Чем depth_

во время парада петросянов тебе доверят нести знамя

jtootf ★★★★★
()
Ответ на: комментарий от PolarFox

Вкурил немного плюсового кода, обратил внимание, что там многие пишут не getNext() в классах, например, а просто next(). При учете того, что внутри класса есть сущность с названием next, префикс выглядит разумно.

DiKeert ★★
() автор топика
Ответ на: комментарий от DiKeert

Вкурил немного плюсового кода, обратил внимание, что там многие пишут не getNext() в классах, например, а просто next(). При учете того, что внутри класса есть сущность с названием next, префикс выглядит разумно.

не путайте api и внутреннюю реализацию

shty ★★★★★
()
Ответ на: комментарий от jtootf

Во-первых, после «m» автокомплит предлагает варианты. Во-вторых сразу видно переменные-свойства. Хотя конечно это субъективно. Я пробовал разные варианты, и все равно всегда возвращался к «mField».

elverion
()
Ответ на: комментарий от elverion

это субъективно

exactly my point. лишь бы однородно по проекту было

jtootf ★★★★★
()

Чей гайд? Гугловский? У них есть много хороших вещей, но косяков навалом. Типа out parameters передавать как указатель.

JackyTreehorn
()
Ответ на: комментарий от JackyTreehorn

>Типа out parameters передавать как указатель.

Тут тоже можно поспорить. Запись foo(&a) сразу говорит о том что «a» меняется.

elverion
()
Ответ на: комментарий от elverion

Я бы предпочел избегать таких сайд-эффектов.

ИМХО, лучше когда метод работает не самим объектом, который надо изменить, а получает какие-то параметры из него.

rect->height = foo(rect->width);

DiKeert ★★
() автор топика
Ответ на: комментарий от JackyTreehorn

Типа out parameters передавать как указатель.

это логично, хоть и тащит с собой немного оверхеда

посмотрим

void foo(const Boo& b, Moo* m) {
    b.someMethod();
    m->someMethod();
}

сразу видно какая переменная к чему

единственный косяк, что в Moo* m может быть передано NULL, поэтому надо вставить дополнительно условие проверки:

void foo(const Boo& b, Moo* m) {

    if(!m) return;

    b.someMethod();
    m->someMethod();
}

мне такой подход импонирует

shty ★★★★★
()
Ответ на: комментарий от shty

различать такие переменные особенно хорошо, когда пишешь в exception safety code style

shty ★★★★★
()
Ответ на: комментарий от elverion

Во-первых, после «m» автокомплит предлагает варианты.

После this-> автокомплит тоже предлагает варианты. И тоже сразу видно переменные свойства.

KblCb ★★★★★
()

>У меня возник только один вопрос - а что, this уже не рулит?

Он и не рулил никогда

yoghurt ★★★★★
()
Ответ на: комментарий от DiKeert

Функциональные структуры данных спасут этот мир!

yoghurt ★★★★★
()

> У меня возник только один вопрос - а что, this уже не рулит?

Иногда this встречается, но как правило на плюсах так писать не принято.

anonymous
()
Ответ на: комментарий от KblCb

> После this-> автокомплит тоже предлагает варианты. И тоже сразу видно переменные свойства.

this-> писать дольше

dt1 ★★
()
Ответ на: комментарий от shty

Аргумент «сразу видно» намекает на целесообразность венгерской нотации.
По мне, достаточно задекларировать параметр как const, об остальном позаботится компилятор.

различать такие переменные особенно хорошо, когда пишешь в exception safety code style

А у них исключения низзя - тоже дерьмо имхо.

JackyTreehorn
()
Ответ на: комментарий от DiKeert

> ИМХО, лучше когда метод работает не самим объектом, который надо изменить, а получает какие-то параметры из него.

Программы должны быть, в добавок к остальному, еще и эффективными, поэтому и есть спрос на in-place операции.

anonymous
()

> У меня возник только один вопрос - а что, this уже не рулит?

Может быть все-таки на жабке останетесь? Там this рулит )))

anonymous
()
Ответ на: комментарий от JackyTreehorn

Аргумент «сразу видно» намекает на целесообразность венгерской нотации.

не, ну тут главное без фанатизма

По мне, достаточно задекларировать параметр как const, об остальном позаботится компилятор.

вопрос не в этом, вопрос в том что для пресловутого exception safety важно разделять локальные и неподлежащие изменению данные и данные, предназначенные для выдачи вовне

> различать такие переменные особенно хорошо, когда пишешь в exception safety code style

А у них исключения низзя - тоже дерьмо имхо.

с текущей реализацией исключений в C++, не знаю, не знаю... я избегаю использования исключений, хоть они порой и уместны

вообще исключения хороши только, пожалуй что, в конструкторах, но, если отказаться от rai (что на мой взгляд большое зло), то нужность исключений ставится под вопрос, имхо

shty ★★★★★
()

> а что, this уже не рулит?

Рулит, конечно. Причём именно в описываемом случае - когда надо различить член класса и одноимённую локальную переменную.

LamerOk ★★★★★
()
Ответ на: комментарий от shty

> для пресловутого exception safety важно разделять локальные и неподлежащие изменению данные и данные, предназначенные для выдачи вовне
Если пользоваться правилом «длина ф-ии не больше страницы», никаких проблем не возникает. Или я тебя неправильно понял?

JackyTreehorn
()
Ответ на: комментарий от JackyTreehorn

не, не, подробнее можно прочитать у страуса (achtung, pdf!)

вкратце так:

An operation on an object is said to be exception safe if that operation leaves the object in a valid state when the operation is terminated by throwing an exception.

маленький туториал (честно спёр со stackoverflow):

Writing exception safe code

Writing exception safe code

To write exception safe code, you must know first what level of exception safety each instruction you write is.

For example, a new can throw an exception, but assigning a built-in (e.g. an int, or a pointer) won't fail. A swap will never fail (don't even write a throwing swap), a std::list::push_back can throw...

Exception guarantee

The first thing to understand is that you must be able to evaluate the exception guarantee offered by all of your functions:

  • none : Your code should never offer that. This code will leak everything, and break down at the very first exception thrown.
  • basic : This is the guarantee you must at the very least offer, that is, if an exception is thrown, no resources is leaked, and all objects are still whole
  • strong : The processing will either succeed, or throw an exception, but if it throws, then the data will be in the same state as if the processing had not started at all (this gives a transactional power to C++)
  • nothrow/nofail : The processing will succeed.

Example of code

The following code seems like correct C++, but in truth, offers the «none» guarantee, and thus, it is not correct:

void doSomething(T & t)
{
   t.integer += 1 ;                 // 1. nothrow/nofail
   X * x = new X() ;                // 2. basic : can throw with new and X constructor
   t.list.push_back(x) ;            // 3. strong : can throw
   x.doSomethingThatCanThrow() ;    // 4. basic : can throw
}

I write all my code with this kind of analysis in mind.

The lowest guarantee offered is basic, but then, the ordering of each instruction makes the whole function «none», because if 3. throws, x will leak.

The first thing to do would be to make the function «basic», that is putting x in a smart pointer until it is safely owned by the list:

void doSomething(T & t)
{
   t.integer += 1 ;                 // 1.  nothrow/nofail
   std::auto_ptr<X> x(new X()) ;    // 2.  basic : can throw with new and X constructor
   X * px = x.get() ;               // 2'. nothrow/nofail
   t.list.push_back(px) ;           // 3.  strong : can throw
   x.release() ;                    // 3'. nothrow/nofail
   x.doSomethingThatCanThrow() ;    // 4.  basic : can throw
}

Now, our code offers a «basic» guarantee. Nothing will leak, and all objects will be in a correct state. But we could offer more, that is, the strong guarantee. This is were it can become costly, and this is why not all C++ code is strong. Let's try it:

void doSomething(T & t)
{
   std::auto_ptr<X> x(new X()) ;    // 1. basic : can throw with new and X constructor
   X * px = x.get() ;               // 2. nothrow/nofail
   x.doSomethingThatCanThrow() ;    // 3. basic : can throw

   T t2(t) ;                        // 4. strong : can throw with T copy-constructor
   t2.list.push_back(px) ;          // 5. strong : can throw
   x.release() ;                    // 6. nothrow/nofail
   t2.integer += 1 ;                // 7. nothrow/nofail

   t.swap(t2) ;                     // 8. nothrow/nofail
}

We re-ordered the operations, first creating and setting X to its right value. If any operation fails, then t is not modified, so, operation 1 to 3 can be considered «strong»: If something throws, t is not modified, and X will not leak because it's owned by the smart pointer.

Then, we do a copy t2 of t, and work on this copy from operation 4 to 7. If something throws, t2 is modified, but then, t is still the original. We still offer the strong guarantee.

Then, we swap t and t2. Swap operations should be nothrow in C++, so lets hope the swap you wrote for T is nothrow (if it isn't, rewrite it so it is nothrow).

So, if we reach the end of the function, everything succeeded (No need of a return type) and t has its excepted value. If it fails, then t has still its original value.

Now, offering the strong guarantee could be quite costly, so don't strive to offer the strong guarantee to all your code, but if you can do it without a cost (and C++ inlining and other optimization could make all the code above costless), then do it. The function user will thank you for it.

shty ★★★★★
()
Ответ на: комментарий от shty

может, это и не самый лучший пример, но принцип поясняет хорошо

shty ★★★★★
()
Ответ на: комментарий от shty

> вообще исключения хороши только, пожалуй что, в конструкторах

Перегрузка операторов из той же области

anonymous
()
Ответ на: комментарий от JackyTreehorn

Что такое exception safety, я еще помню из Саттера, но мы слегка отдалились от темы, как мне кажется.

ну ок, чо :) только не удалились, а углубились

вернёмся к исходныи баранам:

вопрос в том что для пресловутого exception safety важно разделять локальные и неподлежащие изменению данные и данные, предназначенные для выдачи вовне

и это удобно

shty ★★★★★
()
Ответ на: комментарий от LamerOk

> Рулит, конечно. Причём именно в описываемом случае - когда надо различить член класса и одноимённую локальную переменную.

LamerOk такой LamerOk ))) Где-где, но в плюсах такой способ не рулит.

anonymous
()
Ответ на: комментарий от JackyTreehorn

да я так, обсудить :)

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

shty ★★★★★
()
Ответ на: комментарий от shty

Понятно, что обсудить, я тоже :)

Вот именно возможность передачи NULL мне не нравится.

JackyTreehorn
()
Ответ на: комментарий от anonymous
class A {
	int a;
	void setA(int a)
	{
		this->a = a;
	}
};

Предложил более красивое решение без всяких «a1»,«_a», «a_»,«ma», «localA» и т.п. быстро, решительно. Иначе левтолстой и нутыпонел.

LamerOk ★★★★★
()
Ответ на: комментарий от LamerOk

> Предложил более красивое решение без всяких «a1»,«_a», «a_»,«ma», «localA» и т.п. быстро, решительно. Иначе левтолстой и нутыпонел.

А ты еще и забавный )))

Загнал сам себя в тупик, отмев всякие «a1»,«_a», «a_»,«ma», «localA» и т.п., а теперь кричишь про то, что this рулит.

anonymous
()
Ответ на: комментарий от anonymous

Я не себя, я тебя загнал в тупик, дурашка. И я не «теперь кричу», а говорил это с самого начала, школонимоус. ))

LamerOk ★★★★★
()
Ответ на: комментарий от LamerOk

> Я не себя, я тебя загнал в тупик, дурашка.

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

anonymous
()
Ответ на: комментарий от JackyTreehorn

То нельзя - это нельзя. Почему бы им не писать на С в таком случае?

DiKeert ★★
() автор топика
Ответ на: комментарий от anonymous

Жабка она конечно няшная, но по мироощущению хочется чего-то менее оторванного от физической реальности.

DiKeert ★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.