Bruce Eckel - Thinking In C++. Volume 2 - Practical Programming

Здесь есть возможность читать онлайн «Bruce Eckel - Thinking In C++. Volume 2 - Practical Programming» весь текст электронной книги совершенно бесплатно (целиком полную версию без сокращений). В некоторых случаях можно слушать аудио, скачать через торрент в формате fb2 и присутствует краткое содержание. Год выпуска: 2003, ISBN: 2003, Издательство: Prentice Hall, Жанр: Программирование, на английском языке. Описание произведения, (предисловие) а так же отзывы посетителей доступны на портале библиотеки ЛибКат.

Thinking In C++. Volume 2: Practical Programming: краткое содержание, описание и аннотация

Предлагаем к чтению аннотацию, описание, краткое содержание или предисловие (зависит от того, что написал сам автор книги «Thinking In C++. Volume 2: Practical Programming»). Если вы не нашли необходимую информацию о книге — напишите в комментариях, мы постараемся отыскать её.

Best selling author Bruce Eckel has joined forces with Chuck Allison to write
, the sequel to the highly received and best selling
. Eckel is the master of teaching professional programmers how to quickly learn cutting edge topics in C++ that are glossed over in other C++ books. In
, the authors cover the finer points of exception handling, defensive programming and string and stream processing that every C++ programmer needs to know. Special attention is given to generic programming where the authors reveal little known techniques for effectively using the Standard Template Library. In addition, Eckel and Allison demonstrate how to apply RTTI, design patterns and concurrent programming techniques to improve the quality of industrial strength C++ applications. This book is targeted at programmers of all levels of experience who want to master C++.

Thinking In C++. Volume 2: Practical Programming — читать онлайн бесплатно полную книгу (весь текст) целиком

Ниже представлен текст книги, разбитый по страницам. Система сохранения места последней прочитанной страницы, позволяет с удобством читать онлайн бесплатно книгу «Thinking In C++. Volume 2: Practical Programming», без необходимости каждый раз заново искать на чём Вы остановились. Поставьте закладку, и сможете в любой момент перейти на страницу, на которой закончили чтение.

Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

This would surely be an improvement because function declarations would be more explicit. Unfortunately, you can’t always know by looking at the code in a function whether an exception will be thrown—it could happen because of a memory allocation, for example. Worse, existing functions written before exception handling was introduced may find themselves inadvertently throwing exceptions because of the functions they call (which might be linked into new, exception-throwing versions). Hence, the uninformative situation whereby .

void f();

means, "Maybe I’ll throw an exception, maybe I won’t." This ambiguity is necessary to avoid hindering code evolution. If you want to specify that fthrows no exceptions, use the empty list, as in: .

void f() throw();

Exception specifications and inheritance

Each public function in a class essentially forms a contract with the user; if you pass it certain arguments, it will perform certain operations and/or return a result. The same contract must hold true in derived classes; otherwise the expected "is-a" relationship between derived and base classes is violated. Since exception specifications are logically part of a function’s declaration, they too must remain consistent across an inheritance hierarchy. For example, if a member function in a base class says it will only throw an exception of type A, an override of that function in a derived class must not add any other exception types to the specification list, because that would result in unexpected exceptions for the user, breaking any programs that adhere to the base class interface. You can, however, specify fewer exceptions or none at all , since that doesn’t require the user to do anything differently. You can also specify anything that "is-a" Ain place of Ain the derived function’s specification. Here’s an example .

// C01:Covariance.cpp

// Compile Only!

//{-msc}

#include

using namespace std;

class Base {

public:

class BaseException {};

class DerivedException : public BaseException {};

virtual void f() throw (DerivedException) {

throw DerivedException();

}

virtual void g() throw (BaseException) {

throw BaseException();

}

};

class Derived : public Base {

public:

void f() throw (BaseException) {

throw BaseException();

}

virtual void g() throw (DerivedException) {

throw DerivedException();

}

};

A compiler should flag the override of Derived::f( )with an error (or at least a warning) since it changes its exception specification in a way that violates the specification of Base::f( ). The specification for Derived::g( )is acceptable because DerivedException"is-a" BaseException(not the other way around). You can think of Base/Derivedand BaseException/DerivedExceptionas parallel class hierarchies; when you are in Derived, you can replace references to BaseExceptionin exception specifications and return values with DerivedException. This behavior is called covariance (since both sets of classes vary down their respective hierarchies together). (Reminder from Volume 1: parameter types are not covariant—you are not allowed to change the signature of an overridden virtual function.) .

When not to use exception specifications

If you peruse the function declarations throughout the Standard C++ library, you’ll find that not a single exception specification occurs anywhere! Although this might seem strange, there is a good reason for this seeming incongruity: the library consists mainly of templates, and you never know what a generic might do. For example, suppose you are developing a generic stack template and attempt to affix an exception specification to your pop function, like this:

T pop() throw(logic_error);

Since the only error you anticipate is a stack underflow, you might think it’s safe to specify a logic_erroror some other appropriate exception type. But since you don’t know much about the type T, what if its copy constructor could possibly throw an exception (it’s not unreasonable, after all)? Then unexpected( )would be called, and your program would terminate. The point is that you shouldn’t make guarantees that you can’t stand behind. If you don’t know what exceptions might occur, don’t use exception specifications. That’s why template classes, which constitute 90 percent of the Standard C++ library, do not use exception specifications—they specify the exceptions they know about in documentation and leave the rest to you. Exception specifications are mainly for non-template classes .

Exception safety

In Chapter 7 we’ll take an in-depth look at the containers in the Standard C++ library, including the stack container. One thing you’ll notice is that the declaration of the pop( )member function looks like this:

void pop();

You might think it strange that pop( )doesn’t return a value. Instead, it just removes the element at the top of the stack. To retrieve the top value, call top( )before you call pop( ). There is an important reason for this behavior, and it has to do with exception safety , a crucial consideration in library design .

Suppose you are implementing a stack with a dynamic array (we’ll call it dataand the counter integer count), and you try to write pop( )so that it returns a value. The code for such a pop( )might look something like this:

template

T stack::pop() {

if (count == 0)

throw logic_error("stack underflow");

else

return data[--count];

}

What happens if the copy constructor that is called for the return value in the last line throws an exception when the value is returned? The popped element is not returned because of the exception, and yet counthas already been decremented, so the top element you wanted is lost forever! The problem is that this function attempts to do two things at once: (1) return a value, and (2) change the state of the stack. It is better to separate these two actions into two separate member functions, which is exactly what the standard stackclass does. (In other words, follow the time-worn design practice of cohesion —every function should do one thing well .) Exception-safe code leaves objects in a consistent state and does not leak resources .

You also need to be careful writing custom assignment operators. In Chapter 12 of Volume 1, you saw that operator=should adhere to the following pattern:

1. Make sure you’re not assigning to self. If you are, go to step 6. (This is strictly an optimization.)

2. Allocate new memory required by pointer data members.

3. Copy data from the old memory to the new.

4. Delete the old memory.

5. Update the object’s state by assigning the new heap pointers to the pointer data members.

6. Return *this.

It’s important to not change the state of your object until all the new pieces have been safely allocated and initialized. A good technique is to move all of steps 2 and 3 into a separate function, often called clone( ). The following example does this for a class that has two pointer members, theStringand theInts .

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

Похожие книги на «Thinking In C++. Volume 2: Practical Programming»

Представляем Вашему вниманию похожие книги на «Thinking In C++. Volume 2: Practical Programming» списком для выбора. Мы отобрали схожую по названию и смыслу литературу в надежде предоставить читателям больше вариантов отыскать новые, интересные, ещё непрочитанные произведения.


Отзывы о книге «Thinking In C++. Volume 2: Practical Programming»

Обсуждение, отзывы о книге «Thinking In C++. Volume 2: Practical Programming» и просто собственные мнения читателей. Оставьте ваши комментарии, напишите, что Вы думаете о произведении, его смысле или главных героях. Укажите что конкретно понравилось, а что нет, и почему Вы так считаете.

x