Как бросить значимые данные в исключения? - PullRequest
3 голосов
/ 16 января 2011

Я хотел бы бросить исключения со значимым объяснением (дескриптор сокета, идентификатор процесса, индекс сетевого интерфейса, ...)! Я думал, что использование переменных аргументов работало нормально, но в последнее время я понял, что невозможно расширить класс для реализации других типов исключений. Поэтому я решил использовать std :: ostreamstring в качестве внутреннего буфера для обработки форматирования ... но не компилируется! Я думаю, что это имеет дело с конструкторами копирования. В любом случае вот мой кусок кода:

 <code> class Exception: public std::exception {
public:
  Exception(const char *fmt, ...);
  Exception(const char *fname,
            const char *funcname, int line, const char *fmt, ...);
  //std::ostringstream &Get() { return os_ ; }
  ~Exception() throw();
  virtual const char *what() const throw();</p>

<p>protected:
  char err_msg_[ERRBUFSIZ];
  //std::ostringstream os_;
};

Конструктор переменных arguments не может быть унаследован от! вот почему я подумал о std :: ostringstream! Любой совет, как реализовать такой подход?

Ответы [ 3 ]

2 голосов
/ 16 января 2011

Полагаю, вы имеете в виду, что проблема в том, что ostringstream не копируется. Если я правильно понимаю, как насчет того, чтобы ostringstream член был указателем типа std/boost::shared_ptr? Например:

#include <exception>
#include <sstream>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>

struct E : std::exception {
  boost::shared_ptr< std::ostringstream > os_;
  mutable std::string s_;
  std::ostringstream &Get() { return *os_; } 
  const char *what() const throw() {
    s_ = os_->str();
    return s_.c_str();
  }
  E() : os_( boost::make_shared< std::ostringstream >() ) {}
  ~E() throw() {}
};

int main()
{
  try {
    E e;
    e.Get() << "x";
    throw e;
  }
  catch ( std::exception const& e ) {
    cout<< e.what() <<endl;
  }
}

Надеюсь, это поможет.

2 голосов
/ 17 января 2011

Обычно лучшим решением является определение выделенных типов исключений для разных исключений.Ваш тип SocketException будет принимать дескриптор сокета и так далее.Это исключает необходимость использования аргумента vararg ... в ctor.

Кроме того, вам не понадобится член std::ostringstream os_.Объект ostringstream обычно используется для форматирования текста, но не для сохранения результата.Для этого используйте обычный std::string.

2 голосов
/ 16 января 2011

Передавать ... аргументы немного неудобно, но возможно. Вы должны сначала преобразовать их в va_list. Итак, чтобы ваш производный класс мог передавать формат и аргументы в его базовый класс, можно сделать что-то вроде следующего:

class Exception: public std::exception {
public:
  Exception(const char *fmt, ...)
  {
    va_list ap;
    va_start(ap, fmt);
    this->init(fmt, ap);
    va_end(ap);
  }

  virtual const char *what() const throw();

protected:
  Exception(); // for use from derived class's ctor

  void init(char const* fmt, va_list, ap)
  {
    vsnprintf(err_msg_, sizeof err_msg_, fmt, ap);
  }

  char err_msg_[ERRBUFSIZ];
};

struct Exception2 : Exception
{
  Exception2(const char *fmt, ...)
  {
    va_list ap;
    va_start(ap, fmt);
    this->init(fmt, ap);
    va_end(ap);
  }
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...