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

SequenceWithApply<Gromit, vector> dogs; for(int i = 0; i < 5; i++)

dogs.push_back(new Gromit(i)); dogs.apply(&Gromit::speak, 1); dogs.apply(&Gromit::eat, 2.0f); dogs.apply(&Gromit::sleep, 'z', 3.0); dogs.apply(&Gromit::sit);

} ///:~

Conceptually, it reads more sensibly to say that you’re calling apply( ) for the dogs container.

Why virtual member template functions are disallowed

Nested template classes

Template specializations

Full specialization Partial Specialization

A practical example

There’s nothing to prevent you from using a class template in any way you’d use an ordinary class. For example, you can easily inherit from a template, and you can create a new template that instantiates and inherits from an existing template. If the vector class does everything you want, but you’d also like it to sort itself, you can easily reuse the code and add value to it:

//: C03:Sorted.h

// Template specialization #ifndef SORTED_H

#define SORTED_H #include <vector>

template<class T>

class Sorted : public std::vector<T> { public:

Chapter 15: Multiple Inheritance

137

void sort();

};

template<class T>

void Sorted<T>::sort() { // A bubble sort for(int i = size(); i > 0; i--)

for(int j = 1; j < i; j++) if(at(j-1) > at(j)) {

// Swap the two elements: T t = at(j-1);

at(j-1) = at(j); at(j) = t;

}

}

// Partial specialization for pointers: template<class T>

class Sorted<T*> : public std::vector<T*> { public:

void sort();

};

template<class T>

void Sorted<T*>::sort() {

for(int i = size(); i > 0; i--) for(int j = 1; j < i; j++) if(*at(j-1) > *at(j)) {

// Swap the two elements: T* t = at(j-1);

at(j-1) = at(j); at(j) = t;

}

}

// Full specialization for char*: template<>

void Sorted<char*>::sort() { for(int i = size(); i > 0; i--)

for(int j = 1; j < i; j++) if(strcmp(at(j-1), at(j)) > 0) {

// Swap the two elements: char* t = at(j-1); at(j-1) = at(j);

Chapter 15: Multiple Inheritance

138

at(j) = t;

}

}

#endif // SORTED_H ///:~

The Sorted template imposes a restriction on all classes it is instantiated for: They must contain a > operator. In SString this is added explicitly, but in Integer the automatic type conversion operator int provides a path to the built-in > operator. When a template provides more functionality for you, the trade-off is usually that it puts more requirements on your class. Sometimes you’ll have to inherit the contained class to add the required functionality. Notice the value of using an overloaded operator here – the Integer class can rely on its underlying implementation to provide the functionality.

The default Sorted template only works with objects (including objects of built-in types). However, it won’t sort pointers to objects so the partial specialization is necessary. Even then, the code generated by the partial specialization won’t sort an array of char*. To solve this, the full specialization compares the char* elements using strcmp( ) to produce the proper behavior.

Here’s a test for Sorted.h that uses the unique random number generator introduced earlier in the chapter:

//: C03:Sorted.cpp

// Testing template specialization #include "Sorted.h"

#include "Urand.h" #include "../arraySize.h" #include <iostream> #include <string>

using namespace std;

char* words[] = {

"is", "running", "big", "dog", "a",

};

char* words2[] = {

"this", "that", "theother",

};

int main() { Sorted<int> is; Urand<47> rand;

for(int i = 0; i < 15; i++) is.push_back(rand());

for(int l = 0; l < is.size(); l++) cout << is[l] << ' ';

Chapter 15: Multiple Inheritance

139

cout << endl; is.sort();

for(int l = 0; l < is.size(); l++) cout << is[l] << ' ';

cout << endl;

//Uses the template partial specialization: Sorted<string*> ss;

for(int i = 0; i < asz(words); i++) ss.push_back(new string(words[i]));

for(int i = 0; i < ss.size(); i++) cout << *ss[i] << ' ';

cout << endl; ss.sort();

for(int i = 0; i < ss.size(); i++) cout << *ss[i] << ' ';

cout << endl;

//Uses the full char* specialization: Sorted<char*> scp;

for(int i = 0; i < asz(words2); i++) scp.push_back(words2[i]);

for(int i = 0; i < scp.size(); i++) cout << scp[i] << ' ';

cout << endl; scp.sort();

for(int i = 0; i < scp.size(); i++) cout << scp[i] << ' ';

cout << endl;

}///:~

Each of the template instantiations uses a different version of the template. Sorted<int> uses the “ordinary,” non-specialized template. Sorted<string*> uses the partial specialization for pointers. Lastly, Sorted<char*> uses the full specialization for char*. Note that without this full specialization, you could be fooled into thinking that things were working correctly because the words array would still sort out to “a big dog is running” since the partial specialization would end up comparing the first character of each array. However, words2 would not sort out correctly, and for the desired behavior the full specialization is necessary.

Chapter 15: Multiple Inheritance

140

Соседние файлы в предмете Численные методы
  • #
    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