Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Обработка исключения


Автор: And234 7.12.2005, 08:59
Среда VC6

для примера консоль.
Код

#include "stdafx.h"
#include "ClassGL.h"
#include "Exeptt.h"
int main(int argc, char* argv[])
{
    try {
        ClassGl dse;
        dse.Complite();
        printf("SUCCESS!\n");
    }
    catch(...) {
        printf("catch main!\n");
    }
    return 0;
}

и два класса
1 для обрабоки
Код

class ClassGl  
{
public:
    void Err();
    bool Complite();
    ClassGl();
    virtual ~ClassGl() ;

};
bool ClassGl::Complite()
{
    try
    {
        // почему здесь обработчик?
        // потому-что  проверяемые значения могут быть неверными
        // тогда
        Err(); // принудительно вызываем исключение на метке Д12
        return true;
    }
    catch(Exeptt)
    {
        Err();
        return false;
    }
    return true;
}

void ClassGl::Err()
{
    try {

    }
    catch(...){
        throw Exeptt("msgerr catch 1");
    }
    d12:    
    throw Exeptt("msgerr catch 2");

}


2 класс исключения

Код

class Exeptt  
{
public:
    char *GetMsg();
    Exeptt(char *perrmsg);
    virtual ~Exeptt();

protected:
    char msgerr;
};
Exeptt::Exeptt(char *perrmsg)
{
    msgerr = *perrmsg;
}

Exeptt::~Exeptt()
{

}

char *Exeptt::GetMsg()
{
    return &msgerr;  
}


компилится и работает ОК
но если обозначаю класс исключения в Main()
как
Код

    }
    catch(Exeptt *ex) {
        printf("catch main!\n");


возникает ошибка "abnormal program termination".
Как я могу исправить, с условием обработки исключения этим классом.
Думаю проблема в типах функций.

Автор: Vyacheslav 7.12.2005, 14:39
Где код, в котором непосредственно генерится исключение?

Автор: blackofe 7.12.2005, 18:15
And234
а почему не так?

Код
}
    catch(const Exeptt &ex) {
        printf("catch main! error: &s\n", ex.GetMsg());


я немножко переделал программу. мне такой вариант нравится больше:

Код
class Exeptt {
public:
    Exeptt(const char *perrmsg)            {    msgerr = strdup(perrmsg); }
    virtual ~Exeptt()                    {    delete msgerr; }

    const char *GetMsg() const            {    return msgerr; }

protected:
    char *msgerr;
};

class ClassGl {
public:
    ClassGl() {}
    virtual ~ClassGl() {}

    void Err();
    bool Complite();
};

bool ClassGl::Complite()
{
    try {
        Err();
        return true;
    } catch(const Exeptt &) {
        Err();
        return false;
    }
    return true;
}

void ClassGl::Err()
{
    try {
    } catch(...) {
        throw Exeptt("msgerr catch 1");
    }
    throw Exeptt("msgerr catch 2");
}

int main(int argc, char* argv[])
{
    try {
        ClassGl dse;
        dse.Complite();
        printf("SUCCESS!\n");
    } catch(const Exeptt &ex) {
        printf("catch main! error: %s\n", ex.GetMsg());
    }
    return 0;
}


выдает результат:

catch main! error: msgerr catch 2
Press any key to continue

Автор: And234 7.12.2005, 19:55
blackofe
Огромное спасибо.
То что нужно.

Очень волнует один вопрос.
Код

virtual ~Exeptt()                    {    delete msgerr; }
Очистка обязательна?

Автор: blackofe 7.12.2005, 20:02
Цитата(And234 @ 7.12.2005, 19:55)
Очень волнует один вопрос.
Код

virtual ~Exeptt()                    {    delete msgerr; }
Очистка обязательна?

strdup(perrmsg); аллокирует новую память, копирует туда строку perrmsg и помещает указатель на нее в msgerr. ясное дело, что за собой надо подчищать smile.

хотя, наверное, можно обойтись и без аллокации:

Код
class Exeptt {
public:
    Exeptt(char *perrmsg)            {    msgerr = perrmsg; }

    const char *GetMsg() const            {    return msgerr; }

protected:
    char *msgerr;
};


но мне этот вариант нравится меньше. не люблю, когда изнутри объекта я ссылаюсь на бог весть что. в нашем случае, когда аргументом конструктора Exeptt является константа, оно как бы нестрашно. но если передается указатель на строку, которая где-нибудь по пути удалится - это у меня вызывает не очень приятные ощущения. ;)

Автор: blackofe 7.12.2005, 20:27
вообще я предпочитаю работать со string'ом. вот, к примеру, мой универсальный класс исключений.

Код

#define ZERROR_NOERROR                0L

class ZException {
public:
    ZException(const unsigned long Error = ZERROR_NOERROR, const string Info = "")
                : error(Error), info(Info) {}

    const unsigned long Error() const            {    return error; }
    const string &Info() const                    {    return info; }
    virtual const string Description() const = 0;

private:
    unsigned long error;
    string info;
};


когда я создаю класс, в котором могут генериться исключения, я делаю nested класс:

Код

// A errors:
#define A_E_FATALERROR                1L
#define A_E_NONFATALERROR           2L

class A {
public:
    A() {}
    virtual ~A() {}
    // ...
    void Bad()                    {    throw Exception(A_E_FATALERROR, "Something horrible in Bad()"); }
    void NotTooBad()             {    throw Exception(A_E_NONFATALERROR, "Not too much in NotTooBad()"); }

public:
    class Exception : public ZException {
    public:
        Exception(const unsigned long Error = ZERROR_NOERROR, const string Info = "")
                    : ZException(Error, Info) {}
        const string Description() const;
    };
};


мне остается только имплементировать функцию Description() и я allset.

Код

const string A::Exception::Description() const
{
    switch(Error()) {
    case A_E_FATALERROR:
        return "Fatal error";
    case A_E_NONFATALERROR:
        return "Non-fatal error";
    }
    return "Unknown Error";
}


теперь я могу ловить исключения, причем избирательно. могу как A::Exception, а могу как более общий ZException:

Код

int main(int argc, char* argv[])
{
    A a;
    try {
        a.Bad();
    } catch(const A::Exception &ex) {
        cout << "" << ex.Error() << ", " << ex.Description() << ", " << ex.Info() << endl;
    }
    try {
        a.NotTooBad();
    } catch(const ZException &zex) {
        cout << "" << zex.Error() << ", " << zex.Description() << ", " << zex.Info() << endl;
    }
    return 0;
}

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)