Читаем Thinking In C++. Volume 2: Practical Programming полностью

#endif // SUITE_H ///:~

The Suite class holds pointers to its Test objects 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 TestSuiteError exception. 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 Test class.

//: 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 TestSuite framework wherever it applies throughout the rest of this book.

<p>Debugging techniques</p>

The best debugging habit to get into is to use assertions as explained in the beginning of this chapter; by doing so you’ll be more likely to find logic errors before they cause real trouble. This section contains some other tips and techniques that might help during debugging.

<p>Trace macros</p>

Sometimes it’s helpful to print the code of each statement as it is executed, either to cout or to a trace file. Here’s a preprocessor macro to accomplish this:.

#define TRACE(ARG) cout << #ARG << endl; ARG

Now you can go through and surround the statements you trace with this macro. Of course, it can introduce problems. For example, if you take the statement:.

for(int i = 0; i < 100; i++)

  cout << i << endl;

and put both lines inside TRACE( ) macros, you get this:

TRACE(for(int i = 0; i < 100; i++))

TRACE(  cout << i << endl;)

which expands to this:

cout << "for(int i = 0; i < 100; i++)" << endl;

for(int i = 0; i < 100; i++)

  cout << "cout << i << endl;" << endl;

cout << i << endl;

which isn’t exactly what you want. Thus, you must use this technique carefully.

The following is a variation on the TRACE( ) macro:

#define D(a) cout << #a "=[" << a << "]" << '\n';

If you want to display an expression, you simply put it inside a call to D( ). The expression is displayed, followed by its value (assuming there’s an overloaded operator << for the result type). For example, you can say D(a + b). Thus, you can use this macro any time you want to test an intermediate value to make sure things are okay.

Of course, these two macros are actually just the two most fundamental things you do with a debugger: trace through the code execution and display values. A good debugger is an excellent productivity tool, but sometimes debuggers are not available, or it’s not convenient to use them. These techniques always work, regardless of the situation.

<p>Trace file</p>

DISCLAIMER: This section and the next contain code which is officially unsanctioned by the C++ standard. In particular, we redefine cout and new via macros, which can cause surprising results if you’re not careful. Our examples work on all the compilers we use, however, and provide useful information. This is the only place in this book where we will depart from the sanctity of standard-compliant coding practice. Use at your own risk!

The following code allows you to easily create a trace file and send all the output that would normally go to cout into the file. All you have to do is #define TRACEON and include the header file (of course, it’s fairly easy just to write the two key lines right into your file):.

//: C03:Trace.h

// Creating a trace file

#ifndef TRACE_H

#define TRACE_H

#include

#ifdef TRACEON

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных