2012-06-18 3 views
0

Я создал свой собственный класс исключений, который происходит от runtime_error и получает int в c'tor.виртуальный метод в исключениях

Я хотел бы сделать базовый класс для этого исключения, чтобы использовать полиморфизм, поэтому я мог бы поймать только базовый класс, и в основном я бы поймал производный класс, а затем вызвал метод .what() ,

Таким образом, это базовый класс: (OFC в другом CPP файле я получил baseException :: ~ baseException() {})

class baseException 
{ 
    virtual ~baseException()=0 {} 
    virtual const char* what()=0; 
}; 

И это производный класс:

class myException: public runtime_error, public baseException 
{ 
public: 
    myException(int): runtime_error("Error occured") {} 
    const char* what() {return runtime_error::what();} 
}; 

Но когда в основном я пишу:

catch(baseException* x) 
{ 
cout<<x->what(); 
} 

он просто пропускает его и не входит в блок, даже если MyException наследует фр om baseException. Есть предложения?

+1

Что вы имеете в виду вы не можете? –

+0

и где что() определено? – GazTheDestroyer

+1

Почему бы не позволить 'baseException' наследовать от' std :: runtime_error' и 'myException' только от' baseException'? –

ответ

1

Ваша ссылка на объект baseException; поэтому вы просто знаете методы этого класса. baseException не имеет члена, который называется what(). Это вызывает ошибку. Сделайте baseException исходя из runtime_error или поймайте myException напрямую.

Edit:

Этот фрагмент кода показывает, что Тереза ​​абсолютно никаких причин, почему указки не должны работать вместе с исключениями:

#include <iostream> 
#include <string> 

class A { 
public: 
    virtual int test() = 0; 
}; 

class B : public A { 
public: 
    virtual int test() { 
     return 42; 
    } 
}; 


int _tmain(int argc, _TCHAR* argv[]) 
{ 
    try { 
     throw new std::string("foo"); 
    } catch (std::string* ecx){ 
     std::cout << *ecx << std::endl; 
    } 

    try { 
     throw new B(); 
    } catch (A* ecx) { 
     std::cout << ecx->test() << std::endl; 
    } 
} 

Выход:

Foo

+0

baseException наследует от runtime_error не параметр, так как каждый из моих производных пользовательских исключений отправляет другое сообщение в runtime_error c'tor. – Jjang

+0

@Jjang: затем передать это сообщение через конструктор baseException в runtime_error. – rubenvb

+0

мой ответ содержит пример этого – unkulunkulu

2

Вы должны перехватывать исключения по ссылке (или константной ссылке), а не указателем.

+1

Это должен быть комментарий. –

+0

Почему? так как я могу сделать polyorphysem, если я поймаю по ссылке? – Jjang

+0

Полиморфизм совместим со ссылками, проверьте его – unkulunkulu

2

Ваш baseException не метод what, вы должны, вероятно, просто получить baseException от runtime_error.

class baseException : public runtime_error 
{ 
public: 
    baseException(const std::string& what) : runtime_error(what) {} 
}; 

, а затем

class myException: public baseException 
{ 
public: 
    myException(int): baseException("Error occured") {} 
}; 

Хотя я предпочитаю следующую идиому:

class myException: public baseException 
{ 
public: 
    myException(int x): baseException(getWhatMessage(x)) {} 

private: 
    static std::string getWhatMessage(int x) { /*generate the message*/ } 
}; 

На catch части. Если вы бросаете с помощью throw myException(5), то вы должны поймать как этот

catch(baseException& x) 
{ 
    cout<<x.what(); 
} 
+0

, но каждый из полученных классов исключений имеет другое сообщение и получает разные объекты, некоторые получают ints некоторые строки и т. Д. – Jjang

+0

так? добавьте еще один 'myException2', принимающий' double' в качестве аргумента, в чем проблема? – unkulunkulu

1

UPDATE: этот ответ был основан на оригинальной версии этого вопроса. Теперь кажется, что проблема заключается не в вызове what() (так как вы работали над этим, обновив его в своем базовом классе).Проблема в том, что вы пытаетесь поймать указатель и (я думаю), бросая значение; решение поймать по ссылке:

catch (myException const & ex) { 
    std::cerr << ex.what() << std::endl; 
} 

(если вы исправить вашу декларацию what()const быть, если по какой-то причине вам действительно нужно, чтобы это было не- const, а затем удалить const из catch линии).

оригинальный ответ, описывающий, как позвонить what(), если он не объявлен в baseException:

Я хочу, чтобы поймать baseException*

Вы бы лучше ловить baseException const &; нет разумного способа бросить указатель.

и называют их .what() методы

Если вы хотите вызвать what(), то вы могли бы быть лучше ловить std::exception const & вместо; если вы также не хотите использовать некоторые функции из вашего базового класса. В этом случае, возможно, ваш базовый класс должен наследовать от std::runtime_error; или, возможно, он должен наследовать от std::exception, и в этом случае ваш тип myException должен будет использовать виртуальное наследование.

Если вы действительно хотите получить доступ к what() из ваших классов, как они стоят, то вы должны будете поперечным гипс к std::exception:

catch (myException const & ex) { 
    std::cerr << dynamic_cast<std::exception const &>(ex).what() << '\n'; 
} 
+0

Зачем идти за начинающим в это многократное безумие наследования, а не просто указать правильный способ сделать это? – unkulunkulu

+0

@unkulunkulu: Потому что я не знаю точно, чего пытается добиться ОП, и поэтому я не знаю, что такое «правильный». Один из вариантов, которые я дал, - использовать одно наследование, но я не знаю, удовлетворит ли он его потребности, поэтому я также описал другие варианты. –

Смежные вопросы