LINUX.ORG.RU

Стиль программирования


0

1

Вот столкнулся с двумя видами “проблем” при программировании. Как вы предпочитаете решать эти проблемы?

1. Есть несколько функций, из которых надо выбрать одну из некоторого условия. Эти функции имеют одинаковые параметры:

f1(int a)
f2(int a)

1) можно это реализовать через указатели на функции
2) через функцию f(int a,int cond) которая выберет нужную из них

2. Есть две программы, у которых есть общий код. Для удобства этот код я отделил. Т.е. у меня есть файл file, file1, file2.
В этих программах есть свои функции, но параметры у них совпадают. Поэтому можно сделать следующее:

1) в file держать две функции f1, f2
2) держать в file1 свою функцию f, а в file2 свою функцию f и собирать их с разными файлами
3) реализовать через указатели на функцию

З.ы. прошу сильно не пинать, а поделиться опытом.

★★★★★

Последнее исправление: Zodd (всего исправлений: 1)

Можно еще ооп пытаться осиливать.

Sonsee
()

1. Есть несколько функций, из которых надо выбрать одну из некоторого условия.

3) if (cond) f1(a) else f2(a)

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

3) if (cond) f1(a) else f2(a)

Я примерно так и сделал, только cond у меня определяется через еще сложную функцию, а число функций много.

Zodd ★★★★★
() автор топика

указатели имеет смысл применять, когда тебе надо определить функцию, которая юудет использоваться на протяжении большого куска кода и вызываться несколько раз. иначе хватит if-else/switch-case

marvin_yorke ★★★
()

1) можно это реализовать через указатели на функции

просто к сведению: несколько раз обсуждалось, тестировалось и так далее - выбор инвариантов через if..else switch..case быстрее, потому как даёт компилятору возможности для оптимизации.

ЗЫ - без понятия смысловой нагрузки ваших функций, все советы - сферические кони в вакууме.

MKuznetsov ★★★★★
()

1. =1 Добавляем, а не изменяем.

свои функции, но параметры у них совпадают

«имеют одинаковые сигнатуры вызова»

2. =3. Аналогично, как и в (1)

malbolge ★★
()

1. Если функций несколько, можно сделать выбор через if/switch. Когда много, дешевле использовать таблицу колбэков: clbtbl[xxx](42).

2. Наверное не понял вопрос... Между несколькими проектами не держу одни и те же файлы. Редко бывают копии, которые лень оформлять в библиотеки. В таком случае не зазорно изменять каждый файл в рамках своего проекта.

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

А какая разница???

а как Вы думаете? ;)

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

Ну, имхо это из пушки по воробью, с учетом стиля изложения ТС

надо всегда стремиться осваивать новые горизонты

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

if (cond) f1(a) else f2(a)

Ламерство, здесь нужно использовать switch.

ога - замените конструкции if..else на switch..case

switch(cond) {
  case(0):f2();
  default:f1();
}

коллеги скажут веское слово, но оно вам непонравится :)

кстати можно сделать КА который проделает эту работу над исходниками перед увольнением :)

MKuznetsov ★★★★★
()

>З.ы. прошу сильно не пинать, а поделиться опытом.

C++.

сложно не пинать...

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

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

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

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

> switch(cond) {

case(0):f2();

default:f1();


}



Я же говорю - ламер вы и не знаете как используется свитч.

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

Между несколькими проектами не держу одни и те же файлы.

Вот когда меняешь в одном проекте, хочется и чтобы в остальных менялось. Надо бы оформить в виде библиотеке...

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

lol. goto наше фсио

Хороший оператор в языке, в котором отсутствуют эксепшны.

ну еще есть уродский вариант делать после каждой ошибки return с передачей кучи параметров для cleanup'а вот упрощенный пример

res = call0();
if (res != ok)
	return __FUNCTION__##cleanup(arg1,arg2,...); 
res = call1();
if (res != ok)
	return __FUNCTION__##cleanup(arg1,arg2,...); 
res = call2();
if (res != ok)
	return __FUNCTION__##cleanup(arg1,arg2,...); 
покрывает некоторые случаи где обычно нужен goto но чтоб посмотреть код обработки ошибок и очистки ресурсов приходится лезьт в другую функцию и плодятся имена имя_целевой_функции_cleanup вдобавок с goto мы выпригиваем в конец функции чистим и выходим все в одном месте перед глазами если не испытываеш фобии к goto то с ним нагляднее и не надо плодить дубликаты типа имя_целевой_функции_cleanup хотя в последней моей утилите именно так обрабатывается несколько функции со сложной логикой именно из за предрассудков к goto

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

C++

Если ты пишешь в ООП-стиле, то у тебя нет «функций». Используй полиморфизм.

всегда поражал такой однобокий взгляд на вещи «ООП головного мозга»

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

Я сказал «если, то», где тут однобокость?

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

да, с указателями на ф-ции у меня косяк) спасибо за поправку.

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

И тогда вот этот твой монстр:

res = call0();
if (res != ok)
   return __FUNCTION__##cleanup(arg1,arg2,...); 
res = call1();
if (res != ok)
   return __FUNCTION__##cleanup(arg1,arg2,...); 
res = call2();
if (res != ok)
   return __FUNCTION__##cleanup(arg1,arg2,...);

станет вот такой няшкой:

    return (res = call0()) != ok
        || (res = call1()) != ok
        || (res = call2()) != ok;

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

ну во первых она сама должна свои ошибки обрабатывать а возвращать только код ошибки или булево значение как признак успешности неуспешности а во вторых код намного сложнее между callxx можно или вставить goto или return xxx_cleanup иначе зачем бы мне вообще весь этот геморой нужен был

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

Почему бы не возвращать код ошибки тогда? Являющийся элементом enum, естественно.

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

вот этот код получше отображает реальность

err = task0();
if (err != ok)
   return __FUNCTION__##error_handling_and_cleanup(arg1,arg2,...); 
/*
 сложная логика выполнение дальше при ошибке невозможно
 надо или юзать goto для обхода в конец так как уровеь вложенности больше
 одного даже готофобскую идиому do while не заюзаеш или делать return xxx_cleanup
*/ 
err = task1();
if (err != ok)
   return __FUNCTION__##error_handling_and_cleanup(arg1,arg2,...); 
/*
 сложная логика выполнение дальше при ошибке невозможно
 надо или юзать goto для обхода в конец так как уровеь вложенности больше
 одного даже готофобскую идиому do while не заюзаеш или делать return xxx_cleanup
*/ 
err = task2();
if (err != ok)
   return __FUNCTION__##error_handling_and_cleanup(arg1,arg2,...); 
вот и получается диллема а разносить эту функцию на две небольших это еще больше усложнять жизнь тому кто захочет вникнуть как она работает ему придется скакать между функциями решающими логически одно дело вообщем разбиение только вредит

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

мы и так возвращем но возвращает его xxx_cleanup функция в выражении return мы сначала заходим все подчищаем восстанавливаем прежнее состояние и оттуда возвращаем или код ошибки или булево значение а внешнее выражение return которое и вызвало нас передает его выше по стеку вызвавщей ее функции

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

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

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

А конкретно в твоём случае что за f1 и f2? Что делают?

Задают нагружение для разных задач, схематично:

void force(double q,Geom geom, matrix &F) { ... }
Zodd ★★★★★
() автор топика
Ответ на: комментарий от Obey-Kun

Задание нагрузки, механика, МКЭ.

Zodd ★★★★★
() автор топика

google: ooc.pdf

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

ретарни

Wut?

Это видимо по аналогии с линаксом и абантой :)

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

Этот код был перенесен с фортрана, постепенно его довожу до ума.

вам вообще всё по новой писать надо видимо. Если это конечно плюсы.

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

control() ? is_true() : is_false();
или даже
if(control() ? is_true() : is_false())
    exit(СЛУЧИЛОСЬ_СТРАШНОЕ);
если альтернатив больше двух, и они нумерованы целыми(это важно!) константами - используйте switch-case. Указатели на функции имеет смысл лишь в том случае, если эти указатели: 1) передаются в другие функции (callback например). 2) или объединяются в массивы.

Сколько функций в каждом файле - это уже вопрос стиля. Удобнее, когда немного. И править удобнее и собирать быстрее.

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