Você está na página 1de 5

Class Exercise 12: Templates, Singleton

Object-Oriented Programming (83-131), 5771

1) Template functions
template <typename T> inline T dot_product(int dim, T* a, T* b) { T result = T(); for (int i=0; i<dim; ++i) { result += a[i]*b[i]; } return result; } int main() { int a[3] = { 1, 2, 3}; int b[3] = { 5, 6, 7}; std::cout << "dot_product(3,a,b) = " << dot_product(3,a,b) << endl; std::cout << "dot_product(3,a,a) = " << dot_product(3,a,a) << endl; return 0; }

: ?(T ) T

2) Template specialization
#include<iostream.h> template<typename T> T& min(T& a, T& b) { return a>b ? b : a; } int main() { int a = 2, b = 1; cout << min(a, b) << endl; cout << min(1.2, 3.1) << endl; return 0; } #include<iostream.h> template<class T> T& min(T& a, T& b) { return a>b ? b : a; } int& min(int& a, int& b) { cout << int explicit function\n; return a>b ? b : a; } template<> int& min<int>(int& a, int& b) { cout << int explicit function\n; return a>b ? b : a; } int main() { int a = 4, b = 2; cout << min(1.2, 2.3) << endl; cout << min(a, b) << endl; return 0; }

int

Syntax

3) Templates vs. Macros


#define min(i, j) (((i) < (j)) ? (i) : (j)) int main() { int a = 5, b = 10; cout << "MIN = " << min(a++, b) << endl; cout << "A = " << a << endl; return 0; }

// MIN = 6 // A = 7

Class Exercise 12: Templates, Singleton

Object-Oriented Programming (83-131), 5771

4) Template classes
#ifndef _VECTOR_H_ #define _VECTOR_H_ //============================================ // File: vector.h // Description: The interface of the // vector template class. //============================================ const int DEF_CAPACITY = 100;

The implementation should be in the header file


/////// implementation of class vector /////// //constructor implementation template <class T> Vector<T>::Vector(int size) { m_pData = new T[size]; if(m_pData != NULL) m_iSize = size; else m_iSize = 0; } //copy constructor implementation template <class T> Vector<T>::Vector(const Vector<T>& source) { m_iSize = source.m_iSize; m_pData = new T[m_iSize]; if(m_pData != NULL) { for(int i=0; i<m_iSize; i++) m_pData[i] = source.m_pData[i]; } } //destructor implementation template <class T> Vector<T>::~Vector() { if(m_pData != NULL) { delete [] m_pData; m_pData = NULL; } }

// default type or default value is allowed only // in class template template <class T = int> class Vector { private: T* m_pData; int m_iSize; public: //constructors: Vector(int size = DEF_CAPACITY); Vector(const Vector<T>&); //copy constructor ~Vector(); //access to elements via index T& operator[] (int index) const; //assignment operator Vector<T>& operator= (const Vector<T>&); //size of the vector int Size() const; };

Class Exercise 12: Templates, Singleton template <class T> T& Vector<T>::operator[](int index) const { if ((index<0)||(index>=m_iSize) throw ("Out of bounds"); return m_pData[index]; } template <class T> Vector<T>& Vector<T>::operator=(const Vector<T>& vec) { if(this != &vec) { m_iSize = vec.m_iSize; if(m_pData) delete [] m_pData; m_pData = new T[m_iSize]; assert(m_pData!=NULL); //copy the elements for(int i=0; i<vec.m_iSize; i++) m_pData[i] = vec.m_pData[i]; } //return current object return *this; } template <class T> int Vector<T>::Size() const { //returns the number of elements in the vector return m_iSize; } #endif //_VECTOR_H_

Object-Oriented Programming (83-131), 5771 //use_vector.cpp #include<iostream> #include<assert.h> #include "vector.h" int main() { Vector<int> myvector(50); //uses the default type (int) Vector<> second(40); for(int i=0; i < 50; i++) myvector[i] = i; second = myvector; for( i=0;i<50;i++) cout<<second[i]<<' '; myvector[20] = 9; cout<<endl; for(i=0; i < 50; i++) cout<< myvector[i] <<' '; cout<< myvector[20] <<endl; return 0; }

Output: 0 1 2 16 17 29 30 42 43 0 1 2 16 17 29 30 42 43 3 4 5 18 19 31 32 44 45 3 4 5 18 19 31 32 44 45 6 7 8 20 21 33 34 46 47 9 10 11 12 13 14 15 22 23 24 25 26 27 28 35 36 37 38 39 40 41 48 49

6 7 8 9 10 11 12 13 14 15 9 21 22 23 24 25 26 27 28 33 34 35 36 37 38 39 40 41 46 47 48 49 9

5) Non-type template parameters


template<class T = int, int N = 100> class Stack { T data[N]; // Fixed capacity is N size_t count; public: void push(const T& t) { // Etc. } }; int main() { Stack<short, 50> myFixedStack1; Stack<short> myFixedStack2; Stack<> myFixedStack3; return 0; }

Class Exercise 12: Templates, Singleton

Object-Oriented Programming (83-131), 5771

6) Inheritance of template classes from template classes


template <class T> class IdList : public Vector<T> { public: IdList() : Vector<T>(10) {} void Print() { // int numIds = Size(); int numIds = this->Size(); for(int i = 0; i < numIds; ++i) { // cout << operator[](i) << ' '; cout << (*this)[i] << ' '; } } }; int main() { IdList<short> mylist; for(short i = 0; i < 10; ++i) mylist[i] = i; IdList<short> second = mylist; second.Print(); return 0; }

,T. . ,

7) Inheritance of non-template classes from template classes


class IdList : public Vector<short> { public: IdList() : Vector<short>(10) {} void Print() { int numIds = Size(); for(int i = 0; i < numIds; ++i) { cout << operator[](i) << ' '; } } };

.T-

int main() { IdList mylist; for(short i = 0; i < 10; ++i) mylist[i] = i; IdList second = mylist; second.Print(); return 0; }

Class Exercise 12: Templates, Singleton

Object-Oriented Programming (83-131), 5771

Design Patterns (unrelated to templates) 8) Singleton


class Logger{ public:

static Logger* getInstance();


void writeToLogFile(const char* str); private: Logger() { file.open("log"); } Logger(Logger const&) {} Logger& operator=(Logger const&) {}

// Private so that it can not be called

// copy constructor is private // assignment operator is private

static Logger* m_pInstance; ifstream file;


};

#include "logger.h" // Global static pointer used to ensure a single instance of the class. Logger* Logger::m_pInstance = NULL; Logger* Logger::getInstance() { if (m_pInstance == NULL) m_pInstance = new Logger; return m_pInstance; } Logger* Logger::getInstance() {

This is the standard implementation of singleton, but it doesn't delete the instance upon exit.

Another possibility is to declare the instance as a local static object, so it automatically deleted upon exit.

static Logger instance;


return &instance; }

// instead of static member

void Logger::writeToLogFile(const char* str) { file << str << endl; }

int main() { Logger::getInstance()->writeToLogFile("something"); Logger::getInstance()->writeToLogFile("something else"); return 0; }

Você também pode gostar