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», без необходимости каждый раз заново искать на чём Вы остановились. Поставьте закладку, и сможете в любой момент перейти на страницу, на которой закончили чтение.

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

Интервал:

Закладка:

Сделать

nPass = nFail = 0;

}

inline long Test::getNumPassed() const {

return nPass;

}

inline long Test::getNumFailed() const {

return nFail;

}

inline const ostream* Test::getStream() const {

return osptr;

}

inline void Test::setStream(ostream* osptr) {

this->osptr = osptr;

}

inline void Test::succeed_() {

++nPass;

}

inline void Test::reset() {

nPass = nFail = 0;

}

} // namespace TestSuite

#endif // TEST_H ///:~

There are three virtual functions in the Testclass:

· A virtual destructor

· The function reset( )

· The pure virtual function run( )

As explained in Volume 1, it is an error to delete a derived heap object through a base pointer unless the base class has a virtual destructor. Any class intended to be a base class (usually evidenced by the presence of at least one other virtual function) should have a virtual destructor. The default implementation of the Test::reset( )resets the success and failure counters to zero. You might want to override this function to reset the state of the data in your derived test object; just be sure to call Test::reset( )explicitly in your override so that the counters are reset. The Test::run( )member function is pure virtual, of course, since you are required to override it in your derived class .

The test_( )and fail_( )macros can include file name and line number information available from the preprocessor. We originally omitted the trailing underscores in the names, but the original fail( )macro collided with ios::fail( ), causing all kinds of compiler errors .

Here is the implementation of Test:

//: TestSuite:Test.cpp {O}

#include "Test.h"

#include

#include // Note: Visual C++ requires /GR

using namespace std;

using namespace TestSuite;

void Test::do_test(bool cond,

const std::string& lbl, const char* fname,

long lineno) {

if (!cond)

do_fail(lbl, fname, lineno);

else

succeed_();

}

void Test::do_fail(const std::string& lbl,

const char* fname, long lineno) {

++nFail;

if (osptr) {

*osptr << typeid(*this).name()

<< "failure: (" << lbl << ") , "

<< fname

<< " (line " << lineno << ")\n";

}

}

long Test::report() const {

if (osptr) {

*osptr << "Test \"" << typeid(*this).name()

<< "\":\n\tPassed: " << nPass

<< "\tFailed: " << nFail

<< endl;

}

return nFail;

} ///:~

No rocket science here. The Testclass just keeps track of the number of successes and failures as well as the stream where you want Test::report( )to display the results. The test_( )and fail_( )macros extract the current file name and line number information from the preprocessor and pass the file name to do_test( )and the line number to do_fail( ), which do the actual work of displaying a message and updating the appropriate counter. We can’t think of a good reason to allow copy and assignment of test objects, so we have disallowed these operations by making their prototypes private and omitting their respective function bodies .

Here is the header file for Suite: .

//: TestSuite:Suite.h

#ifndef SUITE_H

#define SUITE_H

#include "../TestSuite/Test.h"

#include

#include

using std::vector;

using std::logic_error;

namespace TestSuite {

class TestSuiteError : public logic_error {

public:

TestSuiteError(const string& s = "")

: logic_error(s) {}

};

class Suite {

public:

Suite(const string& name, ostream* osptr = &cout);

string getName() const;

long getNumPassed() const;

long getNumFailed() const;

const ostream* getStream() const;

void setStream(ostream* osptr);

void addTest(Test* t) throw (TestSuiteError);

void addSuite(const Suite&);

void run(); // Calls Test::run() repeatedly

long report() const;

void free(); // Deletes tests

private:

string name;

ostream* osptr;

vector tests;

void reset();

// Disallowed ops:

Suite(const Suite&);

Suite& operator=(const Suite&);

};

inline

Suite::Suite(const string& name, ostream* osptr)

: name(name) {

this->osptr = osptr;

}

inline string Suite::getName() const {

return name;

}

inline const ostream* Suite::getStream() const {

return osptr;

}

inline void Suite::setStream(ostream* osptr) {

this->osptr = osptr;

}

} // namespace TestSuite

#endif // SUITE_H ///:~

The Suiteclass holds pointers to its Testobjects in a vector. Notice the exception specification on the addTest( )member function. When you add a test to a suite, Suite::addTest( )verifies that the pointer you pass is not null; if it is null, it throws a TestSuiteErrorexception. Since this makes it impossible to add a null pointer to a suite, addSuite( )asserts this condition on each of its tests, as do the other functions that traverse the vector of tests (see the following implementation). Copy and assignment are disallowed as they are in the Testclass .

//: TestSuite:Suite.cpp {O}

#include "Suite.h"

#include

#include

using namespace std;

using namespace TestSuite;

void Suite::addTest(Test* t) throw(TestSuiteError) {

// Verify test is valid and has a stream:

if (t == 0)

throw TestSuiteError(

"Null test in Suite::addTest");

else if (osptr && !t->getStream())

t->setStream(osptr);

tests.push_back(t);

t->reset();

}

void Suite::addSuite(const Suite& s) {

for (size_t i = 0; i < s.tests.size(); ++i) {

assert(tests[i]);

addTest(s.tests[i]);

}

}

void Suite::free() {

for (size_t i = 0; i < tests.size(); ++i) {

delete tests[i];

tests[i] = 0;

}

}

void Suite::run() {

reset();

for (size_t i = 0; i < tests.size(); ++i) {

assert(tests[i]);

tests[i]->run();

}

}

long Suite::report() const {

if (osptr) {

long totFail = 0;

*osptr << "Suite \"" << name

<< "\"\n=======";

size_t i;

for (i = 0; i < name.size(); ++i)

*osptr << '=';

*osptr << "=\n";

for (i = 0; i < tests.size(); ++i) {

assert(tests[i]);

totFail += tests[i]->report();

}

*osptr << "=======";

for (i = 0; i < name.size(); ++i)

*osptr << '=';

*osptr << "=\n";

return totFail;

}

else

return getNumFailed();

}

long Suite::getNumPassed() const {

long totPass = 0;

for (size_t i = 0; i < tests.size(); ++i) {

assert(tests[i]);

totPass += tests[i]->getNumPassed();

}

return totPass;

}

long Suite::getNumFailed() const {

long totFail = 0;

for (size_t i = 0; i < tests.size(); ++i) {

assert(tests[i]);

totFail += tests[i]->getNumFailed();

}

return totFail;

}

void Suite::reset() {

for (size_t i = 0; i < tests.size(); ++i) {

assert(tests[i]);

tests[i]->reset();

}

} ///:~

We will be using the TestSuiteframework wherever it applies throughout the rest of this book .

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

Интервал:

Закладка:

Сделать

Похожие книги на «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