понедельник, 17 ноября 2008 г.

__gnu_cxx и __verbose_terminate_handler

Отвлечемся от std. Рассмотрим пространство имен __gnu_cxx, в котором объявлен __verbose_terminate_handler, позволяющий получить больше информации о возникающей исключительной ситуации. Замечу, что это все тот же заголовочный файл exception.
Рассмотрим следующий код:

int main (int argc, char * const argv[]) {
std::cout << "Hello, World!\n";
std::set_terminate(__gnu_cxx::__verbose_terminate_handler);
int k=120;
if(k>100)
throw std::exception();
else
throw k;
for(int i=k;i<1000;++i)
std::cout<<".";
return 0;
}

На выходе получаем следующее:

[Session started at 2008-11-17 23:42:53 +0300.]
Hello, World!
terminate called after throwing an instance of 'std::exception'
what(): St9exception

Как видно из примера, при возникновении исключительной ситуации выводится дополнительная информация о ней, что в некоторых случаях может быть полезным.

Использование set_terminate

Решил немного написать по поводу set_terminate.
Функция set_terminate объявлена в заголовочном файле exception. Она имеет следующий вид:

terminate_handler set_terminate(terminate_handler) throw().

В качестве параметра функция берет указатель на функцию, которая будет вызвана в случае терминирования программы.
Данный указатель на функцию имеет следующий вид:

void (* pF)(void).

Если мы через функцию set_terminate устанавливаем новый обработчик, то она вернет нам старый, если ранее такой существовал для данной ситуации.
Возникает вопрос: а зачем нужно использовать set_terminate? В ответ можно сказать только следующее, что при ошибке в программе, которая ведет к терминированию этой программы, может возникнуть необходимость сохранить данные, закрыть файлы, записать в лог информацию о причинах ошибки и т.д.
В заключении привожу пример использования:

#include <iostream>
#include <exception>

void func1()
{
std::cout<<"The end"<<std::endl;
}

int main (int argc, char * const argv[]) {
std::cout<< "Hello, World!\n";
std::set_terminate(func1);
throw std::exception();
return 0;
}

В результате работы программы получаем следующее:

[Session started at 2008-11-17 23:10:04 +0300.]
Hello, World!
The end

понедельник, 10 ноября 2008 г.

Книга по С++, которую я прочитал первой

Нашел я и книгу, которую прочитал первой при изучении языка С++. Она мне нравилась простотой и последовательностью изложения. Ее удобно использовать, изучая язык. Мне это в ней и нравилось. В настоящее время я, к сожалению, ее уже не имею в своем распоряжении, чтобы подробнее описать. Причина отсутствия: "подарил школьной библиотеке". Так что в школе, где я учился и работал, стало на одну книгу по С++ больше. "Отличный язык в широкие массы!!!".
А вот и ссылка на книгу:
Язык Си++
В. В. Подбельский

Язык Си++

Книга по С++

На вопрос: "Какую книгу почитать по С++?", я предлагаю прочитать книгу Бьерна Страуструпа. Книга интересная, глубокая. Можно прочитать ее поверхностно, выяснив только те вопросы, которые Вас интересуют, а можно копнуть глубоко, прочитав "от корки до корки". Использовать ее как справочник мне очень нравится. Четкое изложение, наличие примера - все что надо для "прояснения вопроса".

Язык программирования С++
Бьерн Страуструп

Язык программирования С++. Специальное издание


Эту книгу я прочитал не первой, однако, купив ее, пользуюсь постоянно.

Перегрузка операторов перенаправления из потока и в поток

Когда мы используем вывод на консоль, то часто пишем следующий код:
std::cout<<"Hello, world"<<std::endl

Предположим, что мы создали класс следующего вида:
class TestClass{
public:
TestClass();
~TestClass();
private:
int i;
std::string s;
};

Для вывода содержимого класса на экран можно воспользоваться созданным специально для этого методом:
class TestClass{
public:
TestClass();
~TestClass();
void output(); // метод для вывода на консоль
private:
int i;
std::string s;
};

void TestClass::output(){
std::cout<<"i="<<i<<"s="<<s<<std::endl;
}

Тогда вывод для экземпляра будет выглядеть так:
TestClass tc;
tc.output();

Такой вариант возможен, но он очень уж некрасив. Переопределим оператор перенаправления в поток, что позволит нам перенаправлять содержимое экземпляра класса в поток вывода:
TestClass tc;
std::cout<<tc<<std::endl;

Для этого реализуем друга класса следующего вида:
class TestClass{
public:
TestClass();
~TestClass();
friend std::ostream& operator<<(std::ostream& out, const TestClass& c);
private:
int i;
std::string s;
};
std::ostream& operator<<(std::ostream& out, const TestClass& c);

Что содержится в теле данного оператора? В нем должен быть реализован функционал по перенаправлению полей класса в поток вывода, например:
std::ostream& operator<<(std::ostream& out, const TestClass& c)
{
out<<"i="<<c.i;
out<<" s="<<c.s;
return out;
}
Т.к. оператор является другом класса, то он имеет доступ к приватным полям класса, что не требует от нас делать их публичными.

Теперь, используя написанный код, можно выводить содержимое класса на консоль:

TestClass tc;
std::cout<<tc<<std::endl;
TestClass *p=new TestClass();
std::cout<<"second: "<<*p<<std::endl;

пятница, 7 ноября 2008 г.

Еще одна книга

Читать на русском хорошо. Но читать техническую литературу на английском приходится чаще. Можно попрактиковаться при чтении стандарта языка С на английском языке. Соответствующая ссылка приведена ниже:
The C Standard
Standards Institute British
The C Standard : Incorporating Technical Corrigendum 1

Если успеете запастись данной книгой на выходные, то поделитесь своими впечатлениями на тему "Мои английские выходные".

Интересная книга

Хочется поделиться еще одной интересной книгой, которая в настоящий момент доступна для чтения:

C Primer Plus

Стивен Прата

Язык программирования C. Лекции и упражнения


В данной книге очень хорошо и подробно рассмотрен язык. Уделено внимание рассмотрению конкретных примеров. В принципе, эта книга может быть интересно разноуровневым специалистам. Написана известным человеком в данной области. Так что книга "на выходные" есть.