Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» Вопросы по программированию на C/С++

Автор: xdude
Дата сообщения: 26.01.2007 03:32

Цитата:
Сам по себе goto неплох, но вот

В принципе, я тоже начинаю так думать. В этих 2-х подходах есть такой момент: первый повторяет много одного и того-же кода - free(objI) повторяется много раз, а второй более компактный по размеру, но производит много лишних сравнений (if (objI) повторяется сначала перед goto, а потом - после _err), т.е., проигрывает по скорости, хотя, все эти лишние сравнения делаются только в том случае, если произошла ошибка при инициализации одного из объектов, а в таком случае, чаще всего, скорость уже некритична. Но goto - некрасивый подход, ИМХО.
Вот я и думаю, может, найдется третий, более элегантный вариант?


Цитата:
А где malloc?

malloc вызывается в функциях APIfunc1...APIfuncN(). На самом деле, это и не совсем malloс, так как возвращаются не указатели на объекты, а указатели на интерфейсы (т.е., например, IWebBrowser2* obj1), и это не совсем free, вызывается obj1->Release(), но суть от этого не меняется - в любом случае в конце нужно вызывать какую-то функцию, чтобы освободить эти объекты.

Кстати, на самом деле я еще немного протупил: метка _err должна стоять до return SOMETHING (сейчас опять исправил исходный пост), иначе все промежуточные объекты останутся в памяти. В некоторых языках (в Делфи, вроде бы) есть конструкция try ... catch ... finally, и как раз в блоке finally и выполняется работа по уничтожению всего, что должно быть уничтожено в любом случае, независимо от того, возникла ошибка или нет. Но в С++, почему-то, такой возможности не предусмотрели. Жаль.

Добавлено:

Цитата:
Можно так: указатели obj1, obj2,..., objN заносишь в массив, а с массивом всё компактней в цикле

Дык для инициализации каждого объекта вызывается своя функция, и все объекты при этом разнотипные.
Автор: TeXpert
Дата сообщения: 26.01.2007 03:43
xdude

Цитата:
...malloc вызывается в функциях APIfunc1...APIfuncN()

Я так и подозревал.


Цитата:
некоторых языках (в Делфи, вроде бы) есть конструкция try ... catch ... finally, и как раз в блоке finally и выполняется работа по уничтожению всего, что должно быть уничтожено в любом случае, независимо от того, возникла ошибка или нет. Но в С++, почему-то, такой возможности не предусмотрели. Жаль.

Ну почему нету? Если ты делаешь в Windows, то там всё есть, насколько помню. Ты в Рихтера заглядывал?


Цитата:
Дык для инициализации каждого объекта вызывается своя функция

Ну так имена функций -- тоже в массы (массив))!

Добавлено:
Вот выдержка из FAQ:

Цитата:

В:    Если есть указатель (char *) на    имя функции в виде стринга, то как
    эту функцию вызвать?

О:    Наиболее прямолинейный путь - создание таблицы имен и соответствующих
    им указателей:

         int function1(), function2();

         struct {char *name; int (*funcptr)();    } symtab[] =
             {
             "function1",     function1,
             "function2",     function2,
             };

    Ну а теперь нужно поискать в таблице нужное имя    и вызвать функцию,
    используя связанный с именем указатель.
Автор: xdude
Дата сообщения: 26.01.2007 04:08

Цитата:
Ну так имена функций -- тоже в массы

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

Цитата:
Ну почему нету? Если ты делаешь в Windows, то там всё есть, насколько помню. Ты в Рихтера заглядывал?

В том-то и дело, что только у виндовса это и есть. "Microsoft specific", блин А я пишу кросс-платформенные приложения.

Добавлено:

Цитата:
Ну а теперь нужно поискать в таблице нужное имя и вызвать функцию,
используя связанный с именем указатель.

А это уж совсем из области интерпретаторов Короче, чтобы нормально писать на С/С++ - нужно написать интерпретатор какого-нибуть скриптового языка. и писать на нём
Автор: TeXpert
Дата сообщения: 26.01.2007 04:11
xdude

Цитата:
В том-то и дело, что только у виндовса это и есть. "Microsoft specific", блин

Ты непоследователен. Тогда зачем плач по Делфям?)

Добавлено:

Цитата:
А это уж совсем из области интерпретаторов

Да нет, это из FAQ по С/С++, зря ты злобствуешь.
Автор: xdude
Дата сообщения: 26.01.2007 04:17

Цитата:
Ты непоследователен. Тогда зачем плач по Делфям?

Как раз наоборот последователен: плачу, что в винде и в делфях (недоступных мне) это реализовано, а в стандартном С++ (таком близком и родном) - нет

Добавлено:

Цитата:
зря ты злобствуешь.

Да я не злобствую Просто искать указатель на функцию по её имени в таблице имён - это как раз одна из задач интерпретатора Я когда-то пытался свой скриптовый язык придумать от нечего делать, приходилось такое писать.
Автор: Mickey_from_nsk
Дата сообщения: 26.01.2007 06:40
Есть более элегантный способ освобождать память при выходе из функции (при определенных условиях) - использование вместо malloc функции alloca, которая выделяет память на стеке. Я думаю понятны и плюсы и минусы этого метода.
Второй способ автоматического удаления памяти - auto_ptr или им подобная концепция. То есть, использование специальных объектов, которые при разрушении уничтожают память, если она была выделена.
Автор: xdude
Дата сообщения: 26.01.2007 06:45
Есть функция:
typedef void* (*callback_t) (void*);
int somefunc(int flags, callback_t callback,void* callback_param);
и есть класс Someclass
{
...
virtual void *somemethod();
};

Есть ли возможность передать метод Someclass::somemethod в функцию somefunc? somefunc(flags,(callback_t)this->somemethod,this) не срабатывает, другое всё тоже перепробовал. Пришлось создать вспомогательную функцию, которой передается указатель на объект класса, и которая вызывает ((Someclass*)ptr)->somemethod();
А напрямую никак нельзя?

Добавлено:

Цитата:
malloc функции alloca

Не выйдет, память выделяю не я, а API-функции.

Цитата:
Второй способ автоматического удаления памяти - auto_ptr или им подобная концепция.

Опять же не выйдет:

Цитата:
На самом деле, это и не совсем malloс, так как возвращаются не указатели на объекты, а указатели на интерфейсы (т.е., например, IWebBrowser2* obj1), и это не совсем free, вызывается obj1->Release(),

Если писать что-то типа auto_ptr - то можно замучаться, така как:

Цитата:
для инициализации каждого объекта вызывается своя функция, и все объекты при этом разнотипные.

Для освобождения, соответственно, тоже разные функции. Т.е., например, некоторые объекты освобождаются с помощью LocalFree(obj), некоторые - GlobalFree(obj) или HeapFree(obj), другие - с помощью obj->Release(), некоторые - это даже на объекты, а системные хендлы (HANDLE, HMODULE и т.д.), для одних надо вызывать FreeLibrary(obj), для других - CloseHandle(obj) ну и т.д., т.е., автоматика тут не прокатит, нужен просто наиболее оптимальный стиль написания кода.
Автор: Mickey_from_nsk
Дата сообщения: 26.01.2007 06:57
xdude
Хе-хе... В свое время я покувыркался с этим изрядно. Пока не набрел на оператор ->*. Решение заковыристое, но есть. Там все сводится к тому, что надо правильно объявить прототип callback-метода.
Автор: xdude
Дата сообщения: 26.01.2007 07:01

Цитата:
Пока не набрел на оператор ->*.

Ну опять-таки, так как объекты все разнотипные - то запарюсь я писать для каждого отдельного типа темплейт авто-класса. Или можно, чтобы этот класс ещё и выбирал автоматом, какую функцию использовать: GlobalFree, LocalFree, free, delete, CloseHandle, FreeLibrary, и сам выискивал другую подходящуу, если такой функции в его списке нет?

Добавлено:

Цитата:
правильно объявить прототип callback-метода.

А, то есть прототип объявляется при объявлении переменной? Ну все равно, некоторые функции еще несколько дополнительных параметров просят, с этим как быть? Или вот оператор delete? Хотя, в таком случае можно и auto_ptr использовать.
Автор: Mickey_from_nsk
Дата сообщения: 26.01.2007 09:24

Цитата:
А, то есть прототип объявляется при объявлении переменной?

Нет, при объявлении функции. Потом нужный метод приводится к типу прототипа.
Автор: RedLord
Дата сообщения: 26.01.2007 11:52
xdude


Цитата:
и как раз в блоке finally и выполняется работа по уничтожению всего


в плюсах есть железная идиома: захват ресурса -есть инициализация.
auto_ptr тому пример.


Цитата:
некоторые - GlobalFree(obj) или HeapFree(obj), другие - с помощью obj->Release(),


посмотри в сторону shared_ptr boost'a.
там есть возможность указать функцию освобождения.
Автор: Mickey_from_nsk
Дата сообщения: 26.01.2007 12:42
RedLord

Цитата:
посмотри в сторону shared_ptr boost'a.
там есть возможность указать функцию освобождения.

Поддерживаю.
Вообще, написать класс-освобождатель - очень просто. Единственное что - это надо определиться какого типа освобождатель из API использовать. Для этого, думаю, пойдет концепция стратегий.
Автор: xdude
Дата сообщения: 26.01.2007 22:52
Ну, с классом-освобождателем, теперь, я думаю разберусь Всем спасибо за советы.
Осталось несколько вопросов, ответа на которые так и не прозвучало, а хотелось бы

Цитата:
Есть функция:
typedef void* (*callback_t) (void*);
int somefunc(int flags, callback_t callback,void* callback_param);
и есть класс Someclass
{
...
virtual void *somemethod();
};

Есть ли возможность передать указатель метод Someclass::somemethod в функцию somefunc? somefunc(flags,(callback_t)this->somemethod,this) не срабатывает, другое всё тоже перепробовал. Пришлось создать вспомогательную функцию, которой передается указатель на объект класса, и которая вызывает ((Someclass*)ptr)->somemethod();
А напрямую никак нельзя?


И еще: как лучше/эффективней/удобней перехватывать эксепшены: для каждой функции в отдельности, или для серии функций?

Код:
try
{
...
func1(...);
...
}
catch (e1) { ... }
catch (e2) { ... };
...
try
{
...
func2(...);
...
}
catch (e3) { ... }
catch (e4) { ... };
и т.д.
Автор: RedLord
Дата сообщения: 27.01.2007 01:19
xdude

Цитата:
Есть функция:
typedef void* (*callback_t) (void*);
int somefunc(int flags, callback_t callback,void* callback_param);
и есть класс Someclass
{
...
virtual void *somemethod();
};

Есть ли возможность передать указатель метод Someclass::somemethod в функцию somefunc? somefunc(flags,(callback_t)this->somemethod,this) не срабатывает, другое всё тоже перепробовал. Пришлось создать вспомогательную функцию, которой передается указатель на объект класса, и которая вызывает ((Someclass*)ptr)->somemethod();
А напрямую никак нельзя?


typedef void* (*callback_t) (); - это указатель на _не_ мемберную функцию и естественно, мембер класса не пройдет

typedef void* (Someclass::*callback_t) () - указатель на мембер класса

struct Someclass
{
        virtual void* somemethod() // 1
        {
            return 0;
        }
        virtual void* somemethod(void*) //2
        {
            return 0;
        }
};
    typedef void* (Someclass::*fn)();
    fn f = &Someclass::somemethod;
    Someclass ss;
    (ss.*f)(); // вызов 1

    typedef void* (Someclass::*fn1)(void*);
    fn1 f1 = &Someclass::somemethod;
    (ss.*f1)(0); // вызов 2

почитай Страуструпа, посмотри в сторону опять таки boost: bind и function тебе помогут
Автор: xdude
Дата сообщения: 27.01.2007 02:00

Цитата:
typedef void* (*callback_t) (); - это указатель на _не_ мемберную функцию и естественно, мембер класса не пройдет

Дык это я знаю. Это тип, и функция, в которую он передается, определены в API, поэтому другой тип я туда передать не могу, переопределить прототип функции - тоже. По сути, ведь мемберская функция вполне подошла бы, так как в мемберскую функцию передаётся указатель на this вместо void*, просто компилятор не пропускает такой каст. Хотя, если это сделать через ассемблер - всё вполне прокатит, я когда-то пробовал. Но сейчас мне ассемблер юзать нельзя.
Автор: Qraizer
Дата сообщения: 27.01.2007 17:28
И правильно делает, что не пропускает. Посмотри на результаты
Код: #include <iostream>

struct Someclass
{
/* ... */
virtual void *somemethod(){return this;};
};

int main()
{
std::cout << &Someclass::somemethod << std::endl;
}
Автор: distance
Дата сообщения: 27.01.2007 20:42
xdude

Цитата:
А вот такой ещё вопросик тогда При программировании WinAPI/COM/OLE сталкивался. В функции последовательно инициализируются какие-то OLE-объекты (причем, это не С++, а С. т.е., классов нет, возвращаются указатели на структуры), для этого нужно вызвать около 10 функций, и если какая-то из них что-то инициализировать не смогла, то все инициализированные перед этим указатели нужно освободить и вернуть из функции код ошибки


Примерно так:


Код:
void* p1 = NULL;
void* p2 = NULL;
void* p3 = NULL;

do
{
if ((p1 = malloc(1)) == NULL)
break;
if ((p2 = malloc(1)) == NULL)
break;
if ((p3 = malloc(1)) == NULL)
break;

// using p1, p2, p3

} while (FALSE);

free(p1);
free(p2);
free(p3);
Автор: xdude
Дата сообщения: 27.01.2007 20:59
distance
Да. интересно. И goto не надо. Но опять же в конце нужно проверять:
if (p1) free(p1);
if (p2) free(p2);
if (p3) free(p3);

А вот как бы замутить так, чтобы совсем без лишних действий?
Автор: distance
Дата сообщения: 27.01.2007 21:59
xdude
Согласно стандарту, передача NULL в функцию освобождения памяти (free) безопасна.

Цитата:
А вот как бы замутить так, чтобы совсем без лишних действий?

it depends
std::auto_ptr, boost::shared_ptr, boost::intrusive_ptr, CComPtr и прочее
Автор: Abs62
Дата сообщения: 27.01.2007 23:30
distance

Цитата:
Согласно стандарту, передача NULL в функцию освобождения памяти (free) безопасна.

Насколько я помню, это относится к operator delete, но никак не к free().
Автор: xdude
Дата сообщения: 27.01.2007 23:40
distance

Цитата:
Согласно стандарту, передача NULL в функцию освобождения памяти (free) безопасна.

Дык я в предыдущих постах писал: там не только free, там разные функции юзаются, и ресурсы разные: от char *buf до HMODULE и HRESOURCE. В принципе, вариант с while, наверное, самый удобный. В любом случае, даже если auto_ptr использовать - всё равно будут лишний раз проверка на NULL делаться, только уже в деструкторе auto_ptr.
Qraizer

Цитата:
И правильно делает, что не пропускает.

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

Код:
file "c.h":
class C
{
...
protected:
virtual void* Callback();
...
};

file "c.cpp":
static void *__callback(void* ptr)
{
((C)ptr)->Callback();
};
Автор: distance
Дата сообщения: 28.01.2007 00:07
Abs62
и для free тоже
... If ptr is a null pointer, no action occurs ...
xdude

Цитата:
там не только free, там разные функции юзаются, и ресурсы разные

либо для каждого ресурса создать свой handle-класс (возможно темплейтный policy-based, возможно применение готового), либо, как уже упоминалось, для boost::shared_ptr можно указать custom deleter, либо просто аккуратно программировать


Цитата:
Тогда другой вопрос: есть класс

ты бы описал конечную цель: что требуется в итоге получить? а то все эти кастинги как-то странновато выглядят...
Автор: xdude
Дата сообщения: 28.01.2007 00:31
distance

Цитата:
ты бы описал конечную цель: что требуется в итоге получить?

Вот это:

Цитата:
Есть функция:
typedef void* (*callback_t) (void*);
int somefunc(int flags, callback_t callback,void* callback_param);
и есть класс Someclass
{
...
virtual void *somemethod();
};

Есть ли возможность передать указатель метод Someclass::somemethod в функцию somefunc? somefunc(flags,(callback_t)this->somemethod,this) не срабатывает, другое всё тоже перепробовал. Пришлось создать вспомогательную функцию, которой передается указатель на объект класса, и которая вызывает ((Someclass*)ptr)->somemethod();
А напрямую никак нельзя?

Выяснили, что напрямую нельзя, т.е., я создал вспомогательную функцию, которая и вызывает необходимый метод класса. проблема в том, что этот метод объявлен как protected. А вспомогательную функцию я сделал static (зачем она где-то ещё нужна, если я её только в одном месте использую). Так вот вопрос: как из static-функции получить доступ к protected-методу класса (static-функция не является методом этого класса, но описана в том же cpp файле, где имплементируются все остальные методы класса)? Объявить её как friend я попробовал - не вышло.

Добавлено:
Если быть более конкретным - то в данном случае мне нужно виртуальный метод Main() класса CThread передать как параметр в API-функцию pthread_create (или виндовую CreateThread), но на самом деле это не имеет значения, т.к. в общем случае функция и класс могут называться как угодно, мне интересен сам подход.
Автор: distance
Дата сообщения: 28.01.2007 00:44
xdude
у тебя изначально неверный подход к проблеме.
поскольку впрямую языковыми средствами задача не решаема, ты пытаешься приделать какие-то костыли в виде статических функций etc, тогда как подлежит пересмотру сама концепция.

напрмер, вместо примитивного указателя на функцию можно использовать boost::function

Код: typedef boost::function<void (void* param)> callback_t;

int somefunc(int flags, callback_t callback,void* callback_param);
Автор: Abs62
Дата сообщения: 28.01.2007 00:54
distance

Цитата:
и для free тоже
... If ptr is a null pointer, no action occurs ...

Значит, это мои давние воспоминания.

xdude

Цитата:
Так вот вопрос: как из static-функции получить доступ к protected-методу класса (static-функция не является методом этого класса, но описана в том же cpp файле, где имплементируются все остальные методы класса)? Объявить её как friend я попробовал - не вышло.

А объявить её статическим методом класса пробовал?
Автор: xdude
Дата сообщения: 28.01.2007 00:57
distance
Я не использую boost. И не хочу. Мне вполне хватает STL. Иначе бы я не парился со своим классом CThread, а взял бы бустовский Boost.Thread.

Добавлено:

Цитата:
А объявить её статическим методом класса пробовал?

А она пройдёт при этом в API-функцию по тайп-касту? Надо будет попробовать.
Автор: xdude
Дата сообщения: 28.01.2007 03:59
Друзья, а есть в STL какая-то функция, которая разбила бы данные в строке, разделенные запятыми (или пробелами, или очередностью символов) на вектор (или список) строк? Типа "test1, test2, test3, test4" на вектор из 4-х строк: "test1", "test2", "test3" и "test4"?
boost не предлагать
Автор: Green2454332
Дата сообщения: 29.01.2007 03:00
Народ 1 вопрос не каво канкретно идти учится чтоб стать програмистом и понемать вас???
Автор: xdude
Дата сообщения: 29.01.2007 03:08
Green2454332
Если чиста канкретна то лучшы школу сначала закончеть и выучить русский изык чтоб тибя понемали, а уже патом изучать изыки праграмиравания.
Автор: xdude
Дата сообщения: 29.01.2007 05:34
Товарищи, что-то втыкнуть никак не могу, мозги уже закипают: как написать универсальный темплейт класса, который будет в своём деструкторе освобождать переменную требуемого типа требуемой функцией? Например, есть MYSQL_RES* ptr, и есть функция mysql_free_result(MYSQL_RES *result), или метод класса-враппера CMysql::FreeResult(MYSQL_RES* res). Что с этим делать?

Добавлено:
Qraizer aka Boroda
По твоему совету взял функцию отсюда:
http://forums.realcoding.net/index.php?s=44184a4106fb132e44572b4597d2a3d3&showtopic=15556&st=15
Заменил там только basic_string<Ch> на string, вызываю:

Код:
char *buf;
...
unsigned int id=from_string<unsigned int>(buf);

Страницы: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193

Предыдущая тема: не знаю как назвать тему :-)


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.