Home arrow C++ Programming arrow Introduction to Templates

Language Translator

Hacking Zone

Hacking Tools
Attacking

Configure Windows

Windows Configuration

Novels

Mix Novels

Human Personality

Body Language
Introduction to Templates PDF Print E-mail
Written by Hemanshu Patel   
Wednesday, 24 October 2007
Article Index
Introduction to Templates
Page 2
Page 3
Page 4
Page 5
Page 6
Page 7
Page 8
Page 9
 

Why iterators?

Up until now you&rsquove seen the mechanics of iterators, but understanding why they are so important takes a more complex example.

It&rsquos common to see polymorphism, dynamic object creation, and containers used together in a true object-oriented program. Containers and dynamic object creation solve the problem of not knowing how many or what type of objects you&rsquoll need. And if the container is configured to hold pointers to base-class objects, an upcast occurs every time you put a derived-class pointer into the container (with the associated code organization and extensibility benefits). As the final code in Volume 1 of this book, this example will also pull together various aspects of everything you&rsquove learned so far &ndash if you can follow this example, then you&rsquore ready for Volume 2.

Suppose you are creating a program that allows the user to edit and produce different kinds of drawings. Each drawing is an object that contains a collection of Shape objects:

//: C16:Shape.h 

>#ifndef SHAPE_H


>#define SHAPE_H


>#include <iostream>


>#include <string>


>


>class Shape {


>public:


> virtual void draw() = 0;


> virtual void erase() = 0;


> virtual ~Shape() {}


>};


>


>class Circle : public Shape {


>public:


> Circle() {}


> ~Circle() { std::cout << "Circle::~Circle
"
; }


> void draw() { std::cout << "Circle::draw
"
;}


> void erase() { std::cout << "Circle::erase
"
;}


>};


>


>class Square : public Shape {


>public:


> Square() {}


> ~Square() { std::cout << "Square::~Square
"
; }


> void draw() { std::cout << "Square::draw
"
;}


> void erase() { std::cout << "Square::erase
"
;}


>};


>


>class Line : public Shape {


>public:


> Line() {}


> ~Line() { std::cout << "Line::~Line
"
; }


> void draw() { std::cout << "Line::draw
"
;}


> void erase() { std::cout << "Line::erase
"
;}


>};


>#endif // SHAPE_H ///:~

This uses the classic structure of virtual functions in the base class that are overridden in the derived class. Notice that the Shape class includes a virtual destructor, something you should automatically add to any class with virtual functions. If a container holds pointers or references to Shape objects, then when the virtual destructors are called for those objects everything will be properly cleaned up.

Each different type of drawing in the following example makes use of a different kind of templatized container class: the PStash and Stack that have been defined in this chapter, and the vector class from the Standard C++ Library. The &ldquouse&rdquo&rsquo of the containers is extremely simple, and in general inheritance might not be the best approach (composition could make more sense), but in this case inheritance is a simple approach and it doesn&rsquot detract from the point made in the example.

//: C16:Drawing.cpp 

>#include <vector> // Uses Standard vector too!

>#include "TPStash2.h"

>#include "TStack2.h"

>#include "Shape.h"

>using namespace std;


>


>// A Drawing is primarily a container of Shapes:

>class Drawing : public PStash<Shape> {


>public:


> ~Drawing() { cout << "~Drawing" << endl; }


>};


>


>// A Plan is a different container of Shapes:

>class Plan : public Stack<Shape> {


>public:


> ~Plan() { cout << "~Plan" << endl; }


>};


>


>// A Schematic is a different container of Shapes:

>class Schematic : public vector<Shape*> {


>public:


> ~Schematic() { cout << "~Schematic" << endl; }


>};


>


>// A function template:

>template<class Iter>


>void drawAll(Iter start, Iter end) {


> while(start != end) {


> (*start)->draw();


> start++;


> }


>}


>


>int main() {


> // Each type of container has

> // a different interface:

> Drawing d;


> d.add(new Circle);


> d.add(new Square);


> d.add(new Line);


> Plan p;


> p.push(new Line);


> p.push(new Square);


> p.push(new Circle);


> Schematic s;


> s.push_back(new Square);


> s.push_back(new Circle);


> s.push_back(new Line);


> Shape* sarray[] = {


> new Circle, new Square, new Line


> };


> // The iterators and the template function

> // allow them to be treated generically:

> cout << "Drawing d:" << endl;


> drawAll(d.begin(), d.end());


> cout << "Plan p:" << endl;


> drawAll(p.begin(), p.end());


> cout << "Schematic s:" << endl;


> drawAll(s.begin(), s.end());


> cout << "Array sarray:" << endl;


> // Even works with array pointers:

> drawAll(sarray,


> sarray + sizeof(sarray)/sizeof(*sarray));


> cout << "End of main" << endl;


>} ///:~

The different types of containers all hold pointers to Shape and pointers to upcast objects of classes derived from Shape. However, because of polymorphism, the proper behavior still occurs when the virtual functions are called.

Note that sarray, the array of Shape*, can also be thought of as a container.


Function templates

In drawAll( ) you see something new. So far in this chapter, we have been using only class templates, which instantiate new classes based on one or more type parameters. However, you can as easily create function templates, which create new functions based on type parameters. The reason you create a function template is the same reason you use for a class template: You&rsquore trying to create generic code, and you do this by delaying the specification of one or more types. You just want to say that these type parameters support certain operations, not exactly what types they are.

The function template drawAll( ) can be thought of as an algorithm (and this is what most of the function templates in the Standard C++ Library are called). It just says how to do something given iterators describing a range of elements, as long as these iterators can be dereferenced, incremented, and compared. These are exactly the kind of iterators we have been developing in this chapter, and also &ndash not coincidentally &ndash the kind of iterators that are produced by the containers in the Standard C++ Library, evidenced by the use of vector in this example.

We&rsquod also like drawAll( ) to be a generic algorithm, so that the containers can be any type at all and we don&rsquot have to write a new version of the algorithm for each different type of container. Here&rsquos where function templates are essential, because they automatically generate the specific code for each different type of container. But without the extra indirection provided by the iterators, this genericness wouldn&rsquot be possible. That&rsquos why iterators are important; they allow you to write general-purpose code that involves containers without knowing the underlying structure of the container. (Notice that, in C++, iterators and generic algorithms require function templates in order to work.)

You can see the proof of this in main( ), since drawAll( ) works unchanged with each different type of container. And even more interesting, drawAll( ) also works with pointers to the beginning and end of the array sarray. This ability to treat arrays as containers is integral to the design of the Standard C++ Library, whose algorithms look much like drawAll( ).

Because container class templates are rarely subject to the inheritance and upcasting you see with &ldquoordinary&rdquo classes, you&rsquoll almost never see virtual functions in container classes. Container class reuse is implemented with templates, not with inheritance.


Summary

Container classes are an essential part of object-oriented programming. They are another way to simplify and hide the details of a program and to speed the process of program development. In addition, they provide a great deal of safety and flexibility by replacing the primitive arrays and relatively crude data structure techniques found in C.

Because the client programmer needs containers, it&rsquos essential that they be easy to use. This is where the template comes in. With templates the syntax for source-code reuse (as opposed to object-code reuse provided by inheritance and composition) becomes trivial enough for the novice user. In fact, reusing code with templates is notably easier than inheritance and composition.

Although you&rsquove learned about creating container and iterator classes in this book, in practice it&rsquos much more expedient to learn the containers and iterators in the Standard C++ Library, since you can expect them to be available with every compiler. As you will see in Volume 2 of this book (downloadable from www.BruceEckel.com), the containers and algorithms in the Standard C++ Library will virtually always fulfill your needs so you don&rsquot have to create new ones yourself.

The issues involved with container-class design have been touched upon in this chapter, but you may have gathered that they can go much further. A complicated container-class library may cover all sorts of additional issues, including multithreading, persistence and garbage collection. 




Digg!Reddit!Del.icio.us!Google!Live!Facebook!Slashdot!Netscape!Technorati!StumbleUpon!Spurl!Wists!Simpy!Newsvine!Blinklist!Furl!Fark!Blogmarks!Yahoo!Smarking!Netvouz!Shadows!RawSugar!Ma.gnolia!PlugIM!Squidoo!BlogMemes!FeedMeLinks!BlinkBits!Tailrank!linkaGoGo!Free social bookmarking plugins and extensions for Joomla! websites! title=
Comments
Add NewSearch
Only registered users can write comments!

Copyright (C) 2007 Alain Georgette / Copyright (C) 2006 Frantisek Hliva. All rights reserved.



Last Updated ( Wednesday, 24 October 2007 )
 
< Prev   Next >
Your Ad Here

Donate us!!

Enter Amount:

RSS socialnet

Add to MyYahoo!
Subscribe in NewsGator Online
Add to Newsburst
Add to Google
Add to My AOL
Add to Pluck
Subscribe in FeedLounge
Add to Windows Live
Add to NetVibes
Subscribe in Rojo
Subscribe in Bloglines
Add to MyMSN
Add to Plusmo for your cellphone
Add to PageFlakes
Add to Technorati
Add to BlinkBits