powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Исключения: за и против
25 сообщений из 158, страница 5 из 7
Исключения: за и против
    #34376539
Akh
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ErVПри каждом случае, когда хоть одна процедура возвращает код неудачи, дальнейшее выполнение функции невозможно. ОДнако все равно надо будет освободить созданные интерфейсы и т.д.

Бряками. :)

Еслиб вайла не было, то выход через вызов функции освобождения ресурсов.
...
Рейтинг: 0 / 0
Исключения: за и против
    #34376894
maXmo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
blindedВяло что-то, вяло обсуждаем... Надо подлить маслица в огонь: А вот что делать, ежели ошибка произошла в одном потоке, а обработать ее надо в другом.Ну в сишах при асинхронном вызове делегата возникшее исключение у тебя вылетит в вызывающем потоке при вызове EndInvoke
...
Рейтинг: 0 / 0
Исключения: за и против
    #34377710
ErV
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
daevaorn ErV ОДнако все равно надо будет освободить созданные интерфейсы и т.д.а если применить RAII? Тогда проблемы в ручном освобождениии не будет
LPDIRECTXFILEDATA - это, к сожалению, кривой Майкрософтовский макрос, за которым скрывается IDirectXFileData* - т.е. COM обьект. Все COM обьекты в примере инициализируются путем передачи в функцию значений типа IDirectXFileData**. - Т.е. указатель на указатель на интерфейс. Поэтому, по-моему, этот вариант "не катит", и не выйдет "удобно" использовать смарт поинтеры (хотя я могу ошибаться).

Akh
Бряками. :)

Разве бряки пройдут вот тут, вне цикла?:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
hr = DirectXFileCreate(&lpDXFileApi);
HRCHECK(hr,"DirectXFileCreate() failed!", CGameLevelException);
hr = lpDXFileApi->RegisterTemplates((LPVOID)D3DRM_XTEMPLATES, D3DRM_XTEMPLATE_BYTES);
HRCHECK(hr,"lpDXFileApi->RegisterTemplates failed!", CGameLevelException);
hr = lpDXFileApi->CreateEnumObject((LPVOID)lpszXFile, DXFILELOAD_FROMFILE, &lpDXFileEnum);
HRCHECK(hr,"lpDXFileApi->CreateEnumObject failed!", CGameLevelException);
hr = lpDXFileEnum->GetNextDataObject(&lpDXFileData);
Здесь идет последовательное создание/инициализация ресурсов. Т.е. - сначала инициализируется lpDXFileApi, потом через lpDXFileApi - lpDXFileEnum, через lpDXFileEnum инициализируется lpDXFileData. В каждой точке возможна неудача...

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

Расшифруйте, пожалуйста, я вас не понял. У меня слово "вайп" упорно ассоциируется с MMORPG. :-\ (переиграл чуть-чуть в свое время)

ЗЫ. Майкрософтвоская программа в аналогичной ситуации использует goto...
...
Рейтинг: 0 / 0
Исключения: за и против
    #34377775
Akh
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ErV
1. Разве бряки пройдут вот тут, вне цикла?:

2. Akh
Еслиб вайла не было, то выход через вызов функции освобождения ресурсов.

Расшифруйте, пожалуйста, я вас не понял. У меня слово "вайп" упорно ассоциируется с MMORPG. :-\ (переиграл чуть-чуть в свое время)

ЗЫ. Майкрософтвоская программа в аналогичной ситуации использует goto...

1. Видел. Но замолчал тему, т.к. можно закрывать учитывая только открытые. Тем более все равно можно свести ко второму случаю :)

2. Например, такое
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
void func_close_safe(Param1 lpDXFileEnum, ...) {
		SAFE_RELEASE(lpDXFileEnum);
		SAFE_RELEASE(lpDXFileData);
		SAFE_RELEASE(lpDXFileApi);
};

void func_work() {
while (SUCCEEDED(hr)){
			//ProcessTemplate(lpDXFileData);
			//waiting until TID_D3DRM_FRAME arrives-----------------------
			const GUID* lpType;
			hr = lpDXFileData->GetType(&lpType);
			//hr=E_FAIL;
                        if (hr!=...) {
			    func_close_safe(lpDXFileEnum, ...)
                            return;
                        }
}


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


int func_close_safe(Param1 lpDXFileEnum, ..., int ret) {
SAFE_RELEASE(lpDXFileEnum);
SAFE_RELEASE(lpDXFileData);
SAFE_RELEASE(lpDXFileApi);
return ret;
};

int func_work() {
while (SUCCEEDED(hr)){
//ProcessTemplate(lpDXFileData);
//waiting until TID_D3DRM_FRAME arrives-----------------------
const GUID* lpType;
hr = lpDXFileData->GetType(&lpType);
//hr=E_FAIL;
if (hr!=...)
return func_close_safe(lpDXFileEnum, ..., error);
}

[/SRC]
...
Рейтинг: 0 / 0
Исключения: за и против
    #34377779
Akh
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ErV
1. Разве бряки пройдут вот тут, вне цикла?:

2. Akh
Еслиб вайла не было, то выход через вызов функции освобождения ресурсов.

Расшифруйте, пожалуйста, я вас не понял. У меня слово "вайп" упорно ассоциируется с MMORPG. :-\ (переиграл чуть-чуть в свое время)

ЗЫ. Майкрософтвоская программа в аналогичной ситуации использует goto...

1. Видел. Но замолчал тему, т.к. можно закрывать учитывая только открытые. Тем более все равно можно свести ко второму случаю :)

2. Например, такое
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
void func_close_safe(Param1 lpDXFileEnum, ...) {
		SAFE_RELEASE(lpDXFileEnum);
		SAFE_RELEASE(lpDXFileData);
		SAFE_RELEASE(lpDXFileApi);
};

void func_work() {
while (SUCCEEDED(hr)){
			//ProcessTemplate(lpDXFileData);
			//waiting until TID_D3DRM_FRAME arrives-----------------------
			const GUID* lpType;
			hr = lpDXFileData->GetType(&lpType);
			//hr=E_FAIL;
                        if (hr!=...) {
			    func_close_safe(lpDXFileEnum, ...)
                            return;
                        }
}


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

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
int func_close_safe(Param1 lpDXFileEnum, ..., int ret) {
		SAFE_RELEASE(lpDXFileEnum);
		SAFE_RELEASE(lpDXFileData);
		SAFE_RELEASE(lpDXFileApi);
   return ret;
};

int func_work() {
while (SUCCEEDED(hr)){
			//ProcessTemplate(lpDXFileData);
			//waiting until TID_D3DRM_FRAME arrives-----------------------
			const GUID* lpType;
			hr = lpDXFileData->GetType(&lpType);
			//hr=E_FAIL;
                        if (hr!=...)
                            return func_close_safe(lpDXFileEnum, ..., error);
}
...
Рейтинг: 0 / 0
Исключения: за и против
    #34378070
ErV
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Akh[quot ErV]
2. Например, такое
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
void func_close_safe(Param1 lpDXFileEnum, ...) {
		SAFE_RELEASE(lpDXFileEnum);
		SAFE_RELEASE(lpDXFileData);
		SAFE_RELEASE(lpDXFileApi);
};

void func_work() {
while (SUCCEEDED(hr)){
			//ProcessTemplate(lpDXFileData);
			//waiting until TID_D3DRM_FRAME arrives-----------------------
			const GUID* lpType;
			hr = lpDXFileData->GetType(&lpType);
			//hr=E_FAIL;
                        if (hr!=...) {
			    func_close_safe(lpDXFileEnum, ...)
                            return;
                        }
}



Тут такая небольшая проблема есть. В том файле, откуда я это выдирал, подобных функций было не меньше десятка (та, что я привел, была просто наиболее простая), и работали они все немного по-разному. Далее, часть интерфейсов является локальными переменными, т.е. функция очистки не подойдет, так как вложенные функции на C++ писать нельзя. И, ИМХО, если делать для каждой такой функции класс будет немного нерационально... хотя, конечно, можно попробовать найти точки пересечения и т.д., но просто (мне кажется) код от этого не станет понятнее...
И ещё. Обратите внимание на throw в блоке catch. До этой функции происходит 5и-6и уровневый вызов функции, работающих по похожему принципу, но с другими интерфейсами, которые, однако, аналогично инициализируются, и при этом инициализация может пройти неудачно... в этом случае return int можно быть коряво...
...
Рейтинг: 0 / 0
Исключения: за и против
    #34378090
daevaorn
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ErV daevaorn ErV ОДнако все равно надо будет освободить созданные интерфейсы и т.д.а если применить RAII? Тогда проблемы в ручном освобождениии не будет
LPDIRECTXFILEDATA - это, к сожалению, кривой Майкрософтовский макрос, за которым скрывается IDirectXFileData* - т.е. COM обьект. Все COM обьекты в примере инициализируются путем передачи в функцию значений типа IDirectXFileData**. - Т.е. указатель на указатель на интерфейс. Поэтому, по-моему, этот вариант "не катит", и не выйдет "удобно" использовать смарт поинтеры (хотя я могу ошибаться).

ну это совсем не проблема, пока правда boost::smart_com нет, но написать простой враппер для COM интерфейсов можно легко, было бы желание.
...
Рейтинг: 0 / 0
Исключения: за и против
    #34378295
ErV
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
daevaorn
ну это совсем не проблема, пока правда boost::smart_com нет, но написать простой враппер для COM интерфейсов можно легко, было бы желание.
Ну, не знаю... там интерфейсы в определенном порядке освобождаться должны...
и, по-моему, в ряде случаев все-таки может быть быстрее использовать исключения или даже goto...
...
Рейтинг: 0 / 0
Исключения: за и против
    #34378438
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Голенков Владимирб.м. неудача при попытке захвата ресурса в конструкторе как раз тот случай?Вот тут согласен. Сложный конструктор который может упасть во время собственно конструирования без исключений упасть не сможет вообще.

blindedНет, конено можно написать и так
template <typename T>
class Stack
{
public:
...
int size() const;
const T& read() const { assert(size()); return ...; }
};
Жить можно, все равно при отладке вылезетА еще, в случае работы со стеком, можно проверять не пуст ли стек перед очередным pop(). Это будет еще больше писанины, зато при дальнейшем сопровождении программы будет сразу видно что в этом месте мы сто процентно не будем читать из пустого стека и этой ошибки не появится вообще.
Ты скажешь: "Ага! Каждый раз делать проверку? Это еще больше писать прийдется!" Да, верно писать прийдется больше, но это будет намного проще сопровождать.

Вот представь что ты берешь чужой код сопровождать и видишь там десяток mystack.pop() разбросаных внутри функции. Ты уверен что предыдущий автор ЭТОЙ функции, убедился что автор класса стека действительно бросает исключение из pop() при пустом стеке? Не уверен? Значит ты сам пойдешь искать исходники класса стека и исследовать как там реализована проверка на пустоту стека.
Вот берем например QT. Смотрим документацию:
QT 4.2.2 T QStack::pop ()
Removes the top item from the stack and returns it. This function assumes that the stack isn't empty.Скажи мне пожалуйста упадет такой код или не упадет, а если упадет то как именно упадет?
Код: plaintext
1.
2.
3.
4.
5.
extern QStack *mystack;
void foo() {
   // пусть мы верим что mystak существует и где-то там в другом модуле создается.
   int i = mystack->pop();
   // 
}
Какое исключение в этом коде я забыл поймать?
А теперь сравни с этим кодом:
Код: plaintext
1.
2.
3.
4.
5.
extern QStack *mystack;
void foo() {
   int i;
   if (! mystak->isEmpty() )  i = mystack->pop(); else generate_error();
   // 
}

MasterZivНу ты стойкий перец! Упорно меня не хочешь понимать.
Решения ОТЛИЧАЮТСЯ тем, что при RETURN тебе надо будет написать обработку ошибок НА ВСЕХ ПРОМЕЖУТОЧНЫХ УРОВНЯХ в стеке вызовов, приведших к вызову данной функции.
Для того и созданы exceptions чтобы с этим бороться. Если бы была разница только в синтаксисе, никому было бы это не нужно.А кому нужно чтобы ошибка проходила несколько промежуточных уровней? Вот это еще один момент который меня просто убивает в идеалогии исключений. Зачем мне исключение сгенерированое драйвером железа если я пишу гуй? Ошибка произошедшая на одном уровне должна быть обработана на этом же уровне или в крайнем случае на следующем уровне. Поднимать ее выше можно, но не правильно. А то в итоге ты можешь доподниматься до того что рисуя клиента к базе данных, и в диалоге "сохранить запись, да/нет" ты будешь обрабатывать ошибки tcpip стека. Либо будешь ловить родителя всех исключений, какой-ниубдь std::exception или ему подобное и обрабатывать общую ошибку без разбора что там в действительности произошло.

MasterZiv(скриптовые языки не берем)А почему это "скриптовые языки не берем"? Чуешь что счет окажется не в пользу исключений? :) На скриптовых мы пишем не меньше чем на компилируемых. А чем дальше, тем больше. Мне вообще кажется, что будущее за скриптами а не компилируемыми исходниками. Так что скриптовые тоже надо учитывать.
...
Рейтинг: 0 / 0
Исключения: за и против
    #34378451
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ErVКасательно исключений и COM. Как можно вот такое реализовать без исключений и goto ?
....
При каждом случае, когда хоть одна процедура возвращает код неудачи, дальнейшее выполнение функции невозможно. ОДнако все равно надо будет освободить созданные интерфейсы и т.д.
А почему без goto? В твоем коде заменяем макрос и try/catch на:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
#define HRCHECK(hr) if (FAILED(hr)) { \
                errorDescription.setError(TEXT(__FILE__), __LINE__, TEXT(__FUNCTION__), hr, TEXT("N/A")); \
                goto error_handler; }
void LoadLevelFromX(LPCSTR lpszXFile){
    ......
    error_handler:
        errorDescription.printout();
        SAFE_RELEASE(...
}
Все остальное ничем от твоего кода не отличается.
...
Рейтинг: 0 / 0
Исключения: за и против
    #34378548
Фотография blinded
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Показываю как надо, чтоб не жевать сопли с обработкой ошибок по всему коду
template <class T>
class DirectXPrt // Ценноссть только в деструкторе
{
public:
typedef T* Pointer;

virtual ~DirextX() { if (ptr) SAFE_RELEASE(ptr); }

// This garbage only for backward compatibility

Pointer operator->() { assert(ptr); return ptr; }
Pointer getPtr() { assert(ptr); return ptr; }
operator T*() { assert(ptr); return ptr; }
protected:
DirectXPtr() { ptr = 0; }
DirectXPtr(Pointer* p) { ptr = p; }
Pointer* ptr;
};

class DirectXFilePtr : public DirectXPtr<LPDIRECTXFILE>
{
public:
DirectXFilePtr();

DirectXFileEnumPtr makeFileEnum(LPSTR s);
void registerTemplates(LPVOID, size_t); // из исходника не ясен 2 параметр
};

class DirectXFileEnumPtr : public DirectXPtr<LPDIRECTXFILEENUMOBJECT>
{
public:
typedef DirectXPtr<LPDIRECTXFILEENUMOBJECT> Parent;
DirectXFileDataPtr getNext();
private:
friend class DirectXFilePtr;
DirectXFileEnum(Pointer p) : parent(p) {}
};

class DirectXFileDataPtr : public DirectXPtr<LPDIRECTXFILEDATA>
{
public:
typedef DirectXPtr<LPDIRECTXFILEDATA> Parent;
GUID getType() const { if (!id) load(); return *id; }
const std::string& getString() const { if (!id) load(); return name; }
private:
friend class DirectXFileEnumPtr;
DirectXFileDataPtr(Pointer p) : parent(p), id(0), name("") {}

void load();

const GUID* id;
std::string nane;
}

// Классы исключений сами допишите, не маленькие
class DirectXFatalException : public std::exception
{
};

class DirectXEnumException : public std::exception
{
};

class DirectXDataException : public std::exeption {};

//------------------------------------------------------------------------------------------
DirectXFilePtr::DirectXFilePtr()
{
if (FAILED(DirectXFileCreate(&ptr))
throw DirectXFatalException();
}

DirectXFileEnumPtr DirectXFilePtr::makeFileEnum(LPSTR s)
{
LPDIRECTXFILEENUMOBJECT p;
if ( FAILED(this->CreateEnumObject((LPVOID)s, DXFILELOAD_FROMFILE, &eptr.get())) )
throw DirectXEnumException();
return DirectXFileEnumPtr(p);
}

void DirectXFilePtr::registerTemplates(LPVOID p, size_t sz)
{
if(FAILED(this->RegisterTemplates(p. sz)))
throw DirectXFatalException();
}

DirectXFileDataPtr DirectXFileEnumPtr::getNext()
{
LPDIRECTXFILEDATA p;
if( FAILED(this->GetNextDataObject(&p)) )
throw DirectXEnumException() ;
return DirectXFileDataPtr(p);
}

void DirectXFileDataPtr::load()
{
if ( FAILED(fileData->GetType(&id)))
throw DirectXDataException();
DWORD size;
if ( FAILED(lpDXFileData->GetName(0, &dwNameSize)) )
throw DirectXDataException();
char buf[128];
if ( FAILED(lpDXFileData->GetName(buf, &size)))
throw DirectXDataException()
name = buf;
}
//------------------------------------------------------------------------------------------
// Зато какая красота в прикладном коде

void LoadLevelFromX(LPCSTR lpszXFile)
{
// Ну это не мое
char szbuf[128];
char szbuf2[128];
ExtractFileName(szbuf2, lpszXFile);
sprintf(szbuf, "%s%d", szbuf2, rand());//GetTickCount());

// А это уже мое, такое даже секретарша поймет
DirectXFilePtr fileApi;
fileApi.registerTemplates((LPVOID)D3DRM_XTEMPLATES, D3DRM_XTEMPLATE_BYTES));
DirectXFileEnumPtr fileEnum = fileApi.makeFileEnum(lpszFile);

try
{
while(true)
{
DirectXFileDataPtr fileData = fileEnum.getNext();
if ( fileData.getType() == TTD__D3DMRFrame && )
{
if (fileData.getName() == "SceneRoot")
{
_D("SceneRoot found\n");
GameLevel_LoadLevel_RootLoop(lpDXFileData);
}
}
else
_D ("Not TID_D3DRMFRAME\n");
}
}
catch ( DirectXEnumException e)
{
;
}
}
// А это не мое
//--------
// Если молния в лоб угодит,
// Значит просто подставлен лоб,
// Или волосы действуют словно магнит,
// Или тело похоже на столб...
...
Рейтинг: 0 / 0
Исключения: за и против
    #34378633
ErV
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
blindedПоказываю как надо, чтоб не жевать сопли с обработкой ошибок по всему коду
...

По-моему, вариант как с goto, так и с исключениями был короче. И проще. И LPDIRECTXFILEDATA это не класс, а typedef, точнее даже макрос
#define LPDIRECTXFILEDATA IDirectXFileData*
где IDirectXFileData - Com интерфейс.
ИМХО, в этом варианте код запутался, фактически остался тем же, особых плюсов я не вижу... ИМХО, нерационально делать вокруг каждого Интерфейса обертку...

ЗЫ. Склоняюсь к варианту с goto... А также к мысли найти и пристукнуть того, кто сказал, что использование goto - "плохой стиль".
...
Рейтинг: 0 / 0
Исключения: за и против
    #34378696
Фотография blinded
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Эта краткость обманчмва. Когда надо будет написать ну одну такую функцию обертка сыграет свою роль
...
Рейтинг: 0 / 0
Исключения: за и против
    #34378707
nikname
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Не заметил - было здесь или нет, но главное, с моей точки зрения, преимущество исключений в том, что они раскручивают стек корректно. Это значит что ошибку можно безопасно передать на любой уровень. Производительность исключения не шибко роняют, если роняют вообще - желающие могут легко написать тест и сравнить.
...
Рейтинг: 0 / 0
Исключения: за и против
    #34378736
ErV
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
blindedКогда надо будет написать ну одну такую функцию обертка сыграет свою роль
Когда будет использоваться 50 разных интерфейсов, написание обертки для каждого замедлит работу... (у вас в примере ряд функции имеют надстройки над стандартными функциями)
Опять же, это ИМХО...
...
Рейтинг: 0 / 0
Исключения: за и против
    #34378741
daevaorn
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ErV blindedКогда надо будет написать ну одну такую функцию обертка сыграет свою роль
Когда будет использоваться 50 разных интерфейсов, написание обертки для каждого замедлит работу... (у вас в примере ряд функции имеют надстройки над стандартными функциями)
Опять же, это ИМХО...
а почему нельзя написать обобщенную обертку для схожих интерфейсов?
...
Рейтинг: 0 / 0
Исключения: за и против
    #34378770
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
blindedПоказываю как надо, чтоб не жевать сопли с обработкой ошибок по всему кодуВот за такой код я и не люблю С++. В примере ErV четко видны блок инициализации, блок работы и блок деструктор. А в этом наборе темплейтов и классов найти что-либо даже с десятого взгляда не представляется возможным. Это тот самый стиль программирования "лапша" за который ругают оператор goto. Код в котором может разобраться только автор и только в течении ближайшей недели после написания.
Добавляем в него исключения и уже сам черт ногу сломит разбираясь как и куда там передается управление, что за чем вызывается.
Священая война против goto началась с утверждения что goto перекидывает управление далеко-далеко по коду. Исключения делают тоже самое, но не по линейному коду а по стеку вызовов.

daevaornа почему нельзя написать обобщенную обертку для схожих интерфейсов?Можно. Проблема только в том, что это очень сложно.
Сложно сделать удобную обертку для чего бы то ни было. Чтобы суметь ее сделать, надо на уровне эксперта разбираться в том для чего делается обертка, а в этом случае обертка уже обычно не нужна. А если ты не эксперт - ты сделашь вместо обертки уродца годного только для сиюминутной задачи. Потащишь этого уродца во второй проект - чуть-чуть облагородишь его, но изначальное уродство заложеное не знанием предмета будет оставаться очень-очень долго. С течением лет это уродство станет почти не заметным, но будет оставаться. В любом случае, чтобы сделать хорошую обертку нужно несколько лет.
...
Рейтинг: 0 / 0
Исключения: за и против
    #34378772
daevaorn
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
White Owl daevaornа почему нельзя написать обобщенную обертку для схожих интерфейсов?]Показываю как надо, чтоб не жевать сопли с обработкой ошибок по всему кодуВот за такой код я и не люблю С++. В примере ErV четко видны блок инициализации, блок работы и блок деструктор. А в этом наборе темплейтов и классов найти что-либо даже с десятого взгляда не представляется возможным. Это тот самый стиль программирования "лапша" за который ругают оператор goto. Код в котором может разобраться только автор и только в течении ближайшей недели после написания.
Добавляем в него исключения и уже сам черт ногу сломит Можно. Проблема только в том, что это очень сложно.
Сложно сделать удобную обертку для чего бы то ни было. Чтобы суметь ее сделать, надо на уровне эксперта разбираться в том для чего делается обертка, а в этом случае обертка уже обычно не нужна. А если ты не эксперт - ты сделашь вместо обертки уродца годного только для сиюминутной задачи. Потащишь этого уродца во второй проект - чуть-чуть облагородишь его, но изначальное уродство заложеное не знанием предмета будет оставаться очень-очень долго. С течением лет это уродство станет почти не заметным, но будет оставаться. В любом случае, чтобы сделать хорошую обертку нужно несколько лет.[/quot]
Ну я не так радикально предлагаю. Всего лишь proxy класс с "правильным" деструктором, который в случае необходимости вызовет release
...
Рейтинг: 0 / 0
Исключения: за и против
    #34378824
Фотография blinded
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
daevaorn ErV blindedКогда надо будет написать ну одну такую функцию обертка сыграет свою роль
Когда будет использоваться 50 разных интерфейсов, написание обертки для каждого замедлит работу... (у вас в примере ряд функции имеют надстройки над стандартными функциями)
Опять же, это ИМХО...
а почему нельзя написать обобщенную обертку для схожих интерфейсов?
Наверное можно, я же не изучал эту библиотеку, да и изучать никакого желания. Все знания извлечены из приведенного автормо куска кода. Потом библиотека написана несолько в ином стиле. хотя бы одно то что производящие методы возвращают код ошибки а указатель на созданный объект записывается в переменную переданную по адресу, не дает возможности безопасно ее обернуть.
Но игра стоит свеч, ежели посмотреть на "клиентский код" то можно заметить что там вообще указателей нет. Нет места для потенциальной ошибки.
...
Рейтинг: 0 / 0
Исключения: за и против
    #34378840
Фотография blinded
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
White Owl blindedПоказываю как надо, чтоб не жевать сопли с обработкой ошибок по всему кодуВот за такой код я и не люблю С++. В примере ErV четко видны блок инициализации, блок работы и блок деструктор. А в этом наборе темплейтов и классов найти что-либо даже с десятого взгляда не представляется возможным. Это тот самый стиль программирования "лапша" за который ругают оператор goto. Код в котором может разобраться только автор и только в течении ближайшей недели после написания.

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

White Owl
Добавляем в него исключения и уже сам черт ногу сломит разбираясь как и куда там передается управление, что за чем вызывается.
Священая война против goto началась с утверждения что goto перекидывает управление далеко-далеко по коду. Исключения делают тоже самое, но не по линейному коду а по стеку вызовов.

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

White Owl
daevaornа почему нельзя написать обобщенную обертку для схожих интерфейсов?Можно. Проблема только в том, что это очень сложно.
Сложно сделать удобную обертку для чего бы то ни было. Чтобы суметь ее сделать, надо на уровне эксперта разбираться в том для чего делается обертка, а в этом случае обертка уже обычно не нужна. А если ты не эксперт - ты сделашь вместо обертки уродца годного только для сиюминутной задачи. Потащишь этого уродца во второй проект - чуть-чуть облагородишь его, но изначальное уродство заложеное не знанием предмета будет оставаться очень-очень долго. С течением лет это уродство станет почти не заметным, но будет оставаться. В любом случае, чтобы сделать хорошую обертку нужно несколько лет.
Не, не несколько лет. Чтобы первую версию написать месяц, ну и полгодика в эксплуатации вытащат наруже большую часть недостатков. Тут вопрос такой стоит ли овчинка выделки? Если сделать и забыть, то по-видимому нет. А вот есжели придется сталкиваться с подобными задачами достаточно часто или еще того хуже придется сопровождать один проект несколько лет, тады ой.
А что касается уродства сего упражнения, дык я энтой библиотеки в глаза не видел, все наваял исключительно глядя в представленный пример, да и времени то потратил - пару часов, в течении которых еще и поужинать успел.
...
Рейтинг: 0 / 0
Исключения: за и против
    #34378865
ErV
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
blinded
Проблема есть, но совсем не в этой области. Как правило код писанный для себя очень плохо задукоментирован, и никогда не знаешь точно какого исключения ждать.

Ну, не знаю... (далее ИМХО) на меня хорошее влияние оказала книга об XP программировании, и я стараюсь писать код так, чтобы документация к нему не требовалась, равно как и комментарии... (на документацию нужно будет дополнительное время, её все равно надо будет переписывать, и фактически, там будет дублирование кода программы в словесном виде...)
Образцом "хорошего" кода для меня на данный момент является Qt. Там логичный стиль, и, в принципе, в том, что там получается, разобраться не очень сложно. К плохому коду отношу то, что творит майкрософт в своих примерах к DirectX SDK, например. Разобраться можно, но там как раз обертки очень старательно используются, и в результате, нужно сидеть довольно долго, чтобы понять логику работы оберток (на изучение работы которых уходит большая часть времени) вместо того, чтобы сразу заняться использованием изучаемого API..


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

По-моему, тогда легче будет написать скелет-функцию или скелет-класс, в котором будут использоваться ключевые моменты, а потом плодить от него потомков. Но не оборачивать каждый интерфейс (просто не вижу в этом смысла - это и так уже готовый обьект, ИМХО, оборачивать его ещё раз будет пустой тратой времени), а воплотить в базовом классе/функции основные используемые алгоритмы...

А что касается уродства сего упражнения, дык я энтой библиотеки в глаза не видел, все наваял исключительно глядя в представленный пример, да и времени то потратил - пару часов, в течении которых еще и поужинать успел.
Это подраздел DirectX - DirectXFile, если вам интересно. Примеров по нему в SDK почти нет. Обертка в данном случае неудобна так как постоянно будет требоваться доступ к переменной, хранящей указатель на интерфейс (например IDirectXFile** и т.д.), который будет засунут, скорее всего, куда-нибудь в private. Сделать с этим ничего нельзя, так как это такая реализация API, исходный код которого не доступен, и которое, к тому же, является системным компонентом. ЕСЛИ бы этого не было, то обертку можно было бы легко написать. Но так как это есть, то потребуется либо куча friend'ов, либо вынести оборачиваемый класс в public либо писать кучу оборачивающих двухстрочных функций для каждого метода исходного интерфейса, а это, по-моему, не самый лучший вариант, так как все удобство обертки сведет к нулю...
...
Рейтинг: 0 / 0
Исключения: за и против
    #34378933
Фотография blinded
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мы несколько отклонились от темы. Вообще-то разговор шел об исключениях. И мне кажется что при правильном их использовании код значительно упрощается. Во всяком случам получившаяся LoadLevelFromХ выглядит значительно менее устрашающе чем исходный вариант, я не говорю об обертке.
А что касается библиотеки DirectX я с ней не пересекаюсь, ибо живу на Unix'e.
...
Рейтинг: 0 / 0
Исключения: за и против
    #34379098
ErV
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
blindedМы несколько отклонились от темы. Вообще-то разговор шел об исключениях. И мне кажется что при правильном их использовании код значительно упрощается. Во всяком случам получившаяся LoadLevelFromХ выглядит значительно менее устрашающе чем исходный вариант, я не говорю об обертке.
А что касается библиотеки DirectX я с ней не пересекаюсь, ибо живу на Unix'e.
Простите, исходный вариант использовал исключения - макрос HRCHECK бросал производный мой собсвтенный класс исключения, который нес в себе информацию об имени функции, строке, и файле, где произошла ошибка...
А получившийся ваш вариант (ничего личного) для меня лично выглядит "более устрашающе" по ряду причин...
Пример я привел так как меня давно этот вопрос интересовал, и здесь он был "в тему" в том числе как вариант проблемы не обязательно привязанной к DirectX и Win32...
Вообще, стандартному C++ , ИМХО, не хватает модели try{...}catch(){..}finally{...}...
...
Рейтинг: 0 / 0
Исключения: за и против
    #34379162
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
blindedА вот что касается лапши - ну не согласен, категорически, каждый класс имеет свою отвественностьи все ясно и понятно, есть файл с объектами, есть перечисление по нему, элемет данных. У каждого класса свой конструктор и деструктор... И вообще это все должно быть разнесено по разным файлам и даже библиотекам...А там вообще классы нужны? А темплейты?
...
Рейтинг: 0 / 0
Исключения: за и против
    #34379347
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
White Owl пишет:

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

В рамках обоих техник можно поднимать или не поднимать ошибки
до любого уровня. Поднимается ошибка или нет - зависит от предметной области
и правильности реализации софта.

> А почему это "скриптовые языки не берем"?

А потому что серьезные проекты на них не пишут.
Ну ладно, фиг с ними, пусь будут.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
25 сообщений из 158, страница 5 из 7
Форумы / C++ [игнор отключен] [закрыт для гостей] / Исключения: за и против
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]