2015-12-09 6 views
0

я следующий код:Как я могу получить один и тот же код метода в подклассе без дублирования кода?

#include <exception> 

class Exception : public std::exception { 
private: 
    const char* MESSAGE = "Exception" 

public: 
    inline virtual const char* what() const throw() { 
     return this->MESSAGE; 
    } 
}; 

class ShoulderROMException : public Exception { 
private: 
    typedef Exception super; 
    const char* MESSAGE = "ShoulderROM exception"; 

protected: 
    static const int MAX_MESSAGE_LENGTH = 200; 
    mutable char composedMessage[ShoulderROMException::MAX_MESSAGE_LENGTH]; 

public: 
    virtual const char* what() const throw() { 
     strcpy(this->composedMessage, super::what()); 
     strcat(this->composedMessage, " -> "); 
     strcat(this->composedMessage, this->MESSAGE); 
     return this->composedMessage; 
    } 
}; 

class KinectInitFailedException : public ShoulderROMException { 
private: 
    typedef ShoulderROMException super; 
    const char* MESSAGE = "Kinect initialization failed." 

public: 
    virtual const char* what() const throw() { 
     strcpy(this->composedMessage, super::what()); 
     strcat(this->composedMessage, " -> "); 
     strcat(this->composedMessage, this->MESSAGE); 
     return this->composedMessage; 
    } 
}; 

Это приводит к записи в журнале вид: Exception -> ShoulderROM exception -> Kinect initialization failed. Это именно то, что я хочу, но я хотел бы избежать очевидного дублирования кода и не могу показаться, чтобы найти (n элегантный) способ сделать это.

Было бы очень приятно, если бы кто-то мог помочь мне здесь. :)

С наилучшими пожеланиями, Лило

+0

Вызывающие 'какое' несколько раз будет в настоящее время не в состоянии странным образом. Рассматривали ли вы использование вложенных исключений? Используете ли вы массивы символов вместо строк из-за безопасности исключений и выделения памяти? – dyp

+0

Вы уже рассмотрели [boost.exceptions] (http://www.boost.org/doc/libs/1_59_0/libs/exception/doc/tutorial_diagnostic_information.html)? – dyp

+0

Да, я считаю, что повышение и несколько связанных с проектом причин не позволяют мне использовать его. Плюс я не являюсь огромным другом форсирования. Я не использую строки, потому что 'std :: exception' заставляет тип' char * '. – Lilo

ответ

1

Спасибо за вашу помощь. Это вдохновило меня. С некоторыми дополнительными идеями сокурсника я придумал это решение, которое отлично работает. :)

#include <exception> 

class Exception : 
    public std::exception { 
private: 
    static const std::string MESSAGE = "Exception"; 

protected: 
    std::string composedMessage; 

public: 
    Exception() : 
    composedMessage(this->MESSAGE) { 
    } 

    virtual const char* what() const throw() { 
     return this->composedMessage.c_str(); 
    } 
}; 

class ShoulderROMException : 
    public Exception { 
private: 
    static const std::string MESSAGE = "ShoulderROM exception"; 

public: 
    ShoulderROMException() { 
     this->appendMessage(this->MESSAGE); 
    } 

    virtual void appendMessage(std::string message) { 
     this->composedMessage += " -> "; 
     this->composedMessage += message; 
    } 
}; 

class KinectInitFailedException : 
    public ShoulderROMException { 
private: 
    static const std::string MESSAGE = "Kinect initialization failed."; 

public: 
    KinectInitFailedException() { 
     this->appendMessage(this->MESSAGE); 
    } 
}; 

Я рассмотрел проблему с неправильной стороны: сверху вниз, а не снизу вверх. ^^

Спасибо за вашу помощь в любом случае и наилучшими пожеланиями, Лило

+0

Почему бы не пройти в конструкторе? Добавьте параметр 'std :: string' в конструктор всех трех типов, в каждом конструкторе добавьте сообщение текущего типа и передайте результат конструктору базового класса. – dyp

+0

Это не слишком усложняло бы бросание исключения, не так ли? – Lilo

+0

[Вот приблизительный эскиз] (http://coliru.stacked-crooked.com/a/3b1e60c849a0bc31) – dyp

1

Реализовать его через общий класс. Я хотел бы переписать код так:

class Exception : public std::exception { 
    static const char* MESSAGE = "Exception" 
    static const int MAX_MESSAGE_LENGTH = 200; 
    mutable char composedMessage[MAX_MESSAGE_LENGTH]; 

public: 
    virtual const char* name() const throw() { 
     return MESSAGE; 
    } 

    virtual const char* what() const throw() { 
     strcpy(this->composedMessage, name()); 
     strcat(this->composedMessage, " -> "); 
     strcat(this->composedMessage, this->MESSAGE); 
     return this->composedMessage; 
    } 
}; 

class ShoulderROMException : public Exception { 
    static const char* MESSAGE = "ShoulderROM exception"; 
public:  
    virtual const char* name() const throw() { 
     return MESSAGE; 
    } 
}; 

class KinectInitFailedException : public ShoulderROMException { 
    static const char* MESSAGE = "Kinect initialization failed." 
public: 
    virtual const char* name() const throw() { 
     return MESSAGE; 
    } 
}; 

Если вы не хотите так много реализации в Exception классе, добавьте еще один из которых оба ShoulderROMException и KinectInitFailedException унаследуют.

Существует другие проблемы с вашим кодом: The MESSAGE члены должны быть static, и ваш способ иметь дело со строками не очень C++ МОГ. Я бы также добавил, что вложение виртуальной функции не имеет никакого смысла.

+0

Спасибо за предложение, мне оно нравится. Проверяют его в следующие минуты. Это 'СООБЩЕНИЕ' должно быть статичным полностью правым, пропустило это. Почему встроенная виртуальная функция не имеет смысла? И что вы имеете в виду при обработке строк? Если вы предположите, что я должен использовать 'std :: string', тогда я должен указать, что' char * 'принудительно используется' std :: exception'. – Lilo

+0

Ваше предложение решает проблему для всех классов, непосредственно полученных из 'Exception', но не для классов, которые являются производными от подклассов из' Exception'. Журнал получает сообщение только от «Исключение» и подкласса «Исключение». Таким образом, в этом примере журнал сказал бы: «Исключение -> Инициализация Kinect не удалась.'вместо" Исключение -> Исключение для исключения из-за плеча -> Инициализация Kinect не выполнена. ". Есть ли способ добиться такой рекурсии без упомянутого дублирования кода? – Lilo

+0

Не путайте вещи: 'std :: exception' запрашивает, что' what' возвращает 'char const *', но это не значит, что вы не можете использовать 'std :: string' в качестве хранилища под ним (когда-либо слышали о' std :: string :: c_str() '?). Кроме того, я пропустил тот факт, что 'KinectInitFailedException' наследуется от' ShoulderROMException', я буду соответствующим образом обновлять свой ответ. –