A minimal commentary is available to understand the code.
Note: the indentation shown here are like 1-2 space.
Vector.h
#ifndef VECTOR_H
#define VECTOR_H
template <class Type>
class Vector{
public:
Vector();
void push_back(const Type& entry);
void pop_back();
void clear();
void resize(int newSize);
int size() const;
/* read */
Type operator[](int index) const;
/* write */
Type& operator[](int index);
/* Nested Iterator class */
class Iterator{
/* Binary operator should be made a function */
friend bool operator==(const Iterator& a, const Iterator& b){
return a.current == b.current;
}
friend bool operator!=(const Iterator& a, const Iterator& b){
return !(a == b); //return !operator==(a, b);
}
public:
Iterator(Vector* parent = NULL);
/* Advances the iterator by an offset */
Iterator& operator+(int offset);
Iterator& operator-(int offset);
Iterator operator++();
Iterator operator++(int);
Iterator operator--();
Iterator operator--(int);
Type operator*();
Type* operator->() const;
/* sets the current pointer with the given pointer */
void setCurrent(Type* given);
private:
Type* current;
};
Iterator begin();
Iterator end();
private:
Type* data;
int theSize, capacity;
Iterator iterator;
};
#endif
Vector.cpp
#include <iostream>
#include "Vector.h"
template <class Type>
Vector<Type>::Vector():theSize(0), capacity(10){
data = new Type[capacity];
iterator = Iterator(this);
}
template <class Type>
void Vector<Type>::push_back(const Type& entry){
if(theSize == capacity)
resize(theSize*2); //doubles the size of the vector if capacity is reached
data[++theSize] = entry; //increments the size, and adds the new entry
}
template <class Type>
void Vector<Type>::pop_back(){
if(theSize == 0)
return;
data[theSize] = NULL;
--theSize;
}
template <class Type>
void Vector<Type>::clear(){
while(theSize > 0)
pop_back();
}
/* Reduce the size to the newSize if current capacity is smaller greater than the newSize.
Otherwise grow the capacity to the demanded newSize, deep copying all the elements in existence. */
template <class Type>
void Vector<Type>::resize(int newSize){
if(newSize > capacity){
Type* backup = data;
data = new Type[newSize];
capacity = newSize;
int j = theSize;
theSize = 0;
for(int i = 0; i < j; ++i){
push_back(backup[i+1]);
}
}
else{
while(newSize < theSize)
pop_back();
}
}
template <class Type>
int Vector<Type>::size() const{
return theSize;
}
template <class Type>
Type Vector<Type>::operator[](int index) const{
return data[index+1];
}
template <class Type>
Type& Vector<Type>::operator[](int index){
return data[index+1];
}
/* returns the Iterator that points to the first element in the data dynamic array */
template <class Type>
typename Vector<Type>::Iterator Vector<Type>::begin(){
iterator.setCurrent(data + 1);
return iterator;
}
/* returns the Iterator that points to the last element in the data dynamic array */
template <class Type>
typename Vector<Type>::Iterator Vector<Type>::end(){
iterator.setCurrent(data + theSize + 1);
return iterator;
}
/*********************** Iterator /***********************/
//template <class Type>
//bool operator==(const typename Vector<Type>::Iterator& a, const typename Vector<Type>::Iterator& b){
// return a.current == b.current;
//}
//
//template <class Type>
//bool operator!=(const typename Vector<Type>::Iterator& a, const typename Vector<Type>::Iterator& b){
// return !(a == b);
//}
template <class Type>
Vector<Type>::Iterator::Iterator(Vector* parent = NULL){
current = (parent) ? (parent->data + 1) : NULL; // sets current to NULL if the parent pointer given is NULL.
}
template <class Type>
typename Vector<Type>::Iterator& Vector<Type>::Iterator::operator+(int offset){
current += offset; // Pointer Arithmetic
return *this;
}
template <class Type>
typename Vector<Type>::Iterator& Vector<Type>::Iterator::operator-(int offset){
current -= offset; // Pointer Arithmetic
return *this;
}
template <class Type>
typename Vector<Type>::Iterator Vector<Type>::Iterator::operator++(){ //pre-increment
++current;
return *this;
}
template <class Type>
typename Vector<Type>::Iterator Vector<Type>::Iterator::operator++(int){ //post-increment
Iterator backup = *this;
++current;
return backup;
}
template <class Type>
typename Vector<Type>::Iterator Vector<Type>::Iterator::operator--(){ //pre-decrement
--current;
return *this;
}
template <class Type>
typename Vector<Type>::Iterator Vector<Type>::Iterator::operator--(int){ //post-decrement
Iterator backup = *this;
--current;
return backup;
}
template <class Type>
Type Vector<Type>::Iterator::operator*(){
return *current;
}
template <class Type>
Type* Vector<Type>::Iterator::operator->() const{
return current;
}
template <class Type>
void Vector<Type>::Iterator::setCurrent(Type* given){
current = given;
}main.cpp
/* This source code is written by Wensheng Chen, anyone can freely redistribute the code under GPL. */
#include <iostream>
#include "Vector.h"
#include "Vector.cpp"
/* Note: Template and separate compilation do not work well together,
one has to include both the header and the implementation file to
achieve the goal of separation compilation. */
using namespace std;
class Cat{
friend ostream& operator<<(ostream& os, const Cat& cat){
os << cat.age;
return os;
}
public:
Cat(){}
Cat(int age):age(age){}
string meow(){
return "meow\n";
}
private:
int age;
};
int main(){
Vector<Cat> number;
for(int i = 0; i < 100; ++i){
number.push_back(i);
}
for(int i = 0; i < number.size(); ++i){
cout << number[i] << endl;
}
cout << "iterator begins now!!\n\n";
int i = 0;
for(Vector<Cat>::Iterator iter = number.begin() + 5; iter != number.end() - 9; ++iter, ++i){
cout << i << ". " << *iter << " " << (iter->meow()).c_str() /* C++ cannot take both a cstring and a string at the same time.*/ << endl;
}
}
No comments:
Post a Comment