Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
B.Eckel - Thinking in C++, Vol.2, 2nd edition.pdf
Скачиваний:
50
Добавлен:
08.05.2013
Размер:
2.09 Mб
Скачать

9:Building stable systems

Shared objects & reference counting

Reference-counted class hierarchies

Finding memory leaks

1.For array bounds checking, use the Array template in C16:Array3.cpp of Volume 1 for all arrays. You can turn off the checking and increase efficiency when you’re ready to ship. (This doesn’t deal with the case of taking a pointer to an array, though

– perhaps that could be templatized somehow as well).

2.Use the C10:MemCheck (wrong chapter number) to guarantee that dynamic memory is released properly.

3.Check for non-virtual destructors in base classes.

423

The canonical object & singlyrooted hierarchies

An extended canonical form

Design by contract Integrated unit testing Dynamic aggregation

[[ This may actually be the “builder” design pattern in some form ]]

The examples we’ve seen so far are illustrative, but fairly simple. It’s useful to see an example that has more complexity so you can see that the STL will work in all situations.

[[ Add a factory method that takes a vector of string]]

The class that will be created as the example will be reasonably complex: it’s a bicycle which can have a choice of parts. In addition, you can change the parts during the lifetime of a Bicycle object; this includes the ability to add new parts or to upgrade from standard-quality parts to “fancy” parts. The BicyclePart class is a base class with many different types, and the Bicycle class contains a vector<BicyclePart*> to hold the various combination of parts that may be attached to a Bicycle:

//: C09:Bicycle.h

// Complex class involving dynamic aggregation #ifndef BICYCLE_H

#define BICYCLE_H #include <vector> #include <string> #include <iostream> #include <typeinfo>

class LeakChecker { int count;

public:

LeakChecker() : count(0) {}

Chapter 16: Design Patterns

424

void print() {

std::cout << count << std::endl;

}

~LeakChecker() { print(); }

void operator++(int) { count++; } void operator--(int) { count--; }

};

class BicyclePart { static LeakChecker lc;

public:

BicyclePart() { lc++; }

virtual BicyclePart* clone() = 0; virtual ~BicyclePart() { lc--; } friend std::ostream&

operator<<(std::ostream& os, BicyclePart* bp) { return os << typeid(*bp).name();

}

friend class Bicycle;

};

enum BPart {

Frame, Wheel, Seat, HandleBar, Sprocket, Deraileur,

};

template<BPart id>

class Part : public BicyclePart { public:

BicyclePart* clone() { return new Part<id>; }

};

class Bicycle { public:

typedef std::vector<BicyclePart*> VBP; Bicycle();

Bicycle(const Bicycle& old);

Bicycle& operator=(const Bicycle& old);

//[Other operators as needed go here:]

//[...]

//[...]

~Bicycle() { purge(); }

//So you can change parts on a bike (but be

//careful: you must clean up any objects you

Chapter 16: Design Patterns

425

// remove from the bicycle!)

VBP& bikeParts() { return parts; } friend std::ostream&

operator<<(std::ostream& os, Bicycle* b); static void print(std::vector<Bicycle*>& vb,

std::ostream& os = std::cout); private:

static int counter; int id;

VBP parts; void purge();

};

//Both the Bicycle and the generator should

//provide more variety than this. But this gives

//you the idea.

struct BicycleGenerator { Bicycle* operator()() {

return new Bicycle;

}

};

#endif // BICYCLE_H ///:~

The operator<< for ostream and Bicycle moves through and calls the operator<< for each BicyclePart, and that prints out the class name of the part so you can see what a Bicycle contains. The BicyclePart::clone( ) member function is necessary in the copy-constructor of Bicycle, since it just has a vector<BicyclePart*> and wouldn’t otherwise know how to copy the BicycleParts correctly. The cloning process, of course, will be more involved when there are data members in a BicyclePart.

BicyclePart::partcount is used to keep track of the number of parts created and destroyed (so you can detect memory leaks). It is incremented every time a new BicyclePart is created and decremented when one is destroyed; also, when partcount goes to zero this is reported and if it goes below zero there will be an assert( ) failure.

If you want to change BicycleParts on a Bicycle, you just call Bicycle::bikeParts( ) to get the vector<BicyclePart*> which you can then modify. But whenever you remove a part from a Bicycle, you must call delete for that pointer, otherwise it won’t get cleaned up.

Here’s the implementation:

//: C09:Bicycle.cpp {O} // Bicycle implementation #include "Bicycle.h" #include <map>

#include <algorithm> #include <cassert>

Chapter 16: Design Patterns

426

using namespace std;

// Static member definitions: LeakChecker BicyclePart::lc; int Bicycle::counter = 0;

Bicycle::Bicycle() : id(counter++) { BicyclePart *bp[] = {

new Part<Frame>,

new Part<Wheel>, new Part<Wheel>, new Part<Seat>, new Part<HandleBar>,

new Part<Sprocket>, new Part<Deraileur>,

};

const int bplen = sizeof bp / sizeof *bp; parts = VBP(bp, bp + bplen);

}

Bicycle::Bicycle(const Bicycle& old)

: parts(old.parts.begin(), old.parts.end()) { for(int i = 0; i < parts.size(); i++)

parts[i] = parts[i]->clone();

}

Bicycle& Bicycle::operator=(const Bicycle& old) { purge(); // Remove old lvalues parts.resize(old.parts.size()); copy(old.parts.begin(),

old.parts.end(), parts.begin()); for(int i = 0; i < parts.size(); i++)

parts[i] = parts[i]->clone(); return *this;

}

void Bicycle::purge() { for(VBP::iterator it = parts.begin();

it != parts.end(); it++) { delete *it;

*it = 0; // Prevent multiple deletes

}

}

ostream& operator<<(ostream& os, Bicycle* b) { copy(b->parts.begin(), b->parts.end(),

ostream_iterator<BicyclePart*>(os, "\n"));

Chapter 16: Design Patterns

427

Соседние файлы в предмете Численные методы
  • #
    08.05.20133.99 Mб22A.Menezes, P.van Oorschot,S.Vanstone - HANDBOOK OF APPLIED CRYPTOGRAPHY.djvu
  • #
  • #
    08.05.20135.91 Mб24B.Eckel - Thinking in Java, 3rd edition (beta).pdf
  • #
  • #
    08.05.20136.09 Mб17D.MacKay - Information Theory, Inference, and Learning Algorithms.djvu
  • #
    08.05.20133.85 Mб15DIGITAL Visual Fortran ver.5.0 - Programmers Guide to Fortran.djvu
  • #
    08.05.20131.84 Mб12E.A.Lee, P.Varaiya - Structure and Interpretation of Signals and Systems.djvu