Пожалуйста, простите мою C++ наивность
Я думал о создании классов исключений, которые наследовали бы от std :: stringstream, чтобы я мог использовать оператор stringstreams << для создания текстовых сообщений об ошибках и в то же время попытаться поймать исключения по типу.
Мой код - это что-то вроде
class ExceptionXYZ : public std::stringstream
{};
Void someFunction()
{
try
{
//do something
}
catch(const ExceptionXYZ& e)
{
//handle XYZ
}
К сожалению, моему компилятору VS2008 это не нравится, и жалуется, что
ошибка C2248: 'std :: basic_ios <_Elem, _Traits> :: basic_ios': не может получить доступ к закрытому члену, объявленному в классе 'std :: basic_ios <_Elem, _Traits>'
basic_ios - отличный прародитель (или около того) строкового потока, и там должно быть какое-то неявное нарушение прав доступа, но между моим чрезвычайно ржавым C++ и компилятором бесполезное сообщение об ошибке (это не говорит мне, что частный член его беспокоит) Im немного потерял.
Я полагаю, что люди все время делают такие вещи (т.е. Бросают исключения с текстом, который нужно поймать по типу).
Помощь будет принята с благодарностью
Вы не можете использовать std::stringstream
в качестве базового класса для исключения, потому что вы не можете копировать или перемещать stringstream
(из-за streambuffer
внутри, если вы посмотрите на сообщение об ошибке), и это требование для объекта, который нужно выбросить. Поэтому, когда я делаю такой код, он не может скомпилироваться:
class ExceptionXYZ : public std::stringstream {};
void test_except() throw (ExceptionXYZ)
{
ExceptionXYZ xyz;
xyz << "This exception is useless";
throw xyz;
}
Вы не должны наследовать классы потоков, чтобы использовать их во время построения. Если вам действительно нужно создать сообщение об ошибке, вы можете скорее сохранить информацию, необходимую для ее сборки по запросу, или построить ее при построении.
Из звуков этого вы хотите сделать что-то вроде этого:
throw ExceptionXYZ() << "some " << information << " or " << other;
Это не будет работать слишком хорошо, потому что operator<<()
будет возвращать std::ostream&
а не объект исключения, который вы хотите.
(Большинство) в STD предназначены для того, чтобы не использоваться в качестве базовых классов. Используйте их только как переменные-члены.
Чтобы дать сообщение своему исключению, вы можете сделать что-то вроде этого:
class ExceptionXYZ
{
public:
ExceptionXYZ(const std::string& msg) : msg_(msg) {}
const std::string& get_message() const { return msg_; }
private:
std::string msg_;
};
std::stringstream ss;
ss << "Error " << 42;
throw ExceptionXYZ(ss.str());
std::streambuf
и различные аспекты). Класс std::istream
и std::ostream
также предназначены для использования в качестве базовых классов, хотя только для потоков, инициализирующих свою соответствующую базу и содержащих необходимые объекты (например, std::filebuf
или std::stringbuf
).
vector
, list
, map
или set
в качестве базового класса ...