真正面向对象的编程需要对象来支持三种特性:封装、继承和多态,多态性使许多实现的一个通用接口,并在不同的情况下,在不同的情况下采取行动。C++支持多种静态(编译时)和动态(运行时)的多态性,语言所支持的功能上面。编译时多态性不允许某些运行时的决定,而运行时多态性通常会导致性能损失。静态多态性不是真正的多态现象,包括函数重载,操作符重载和模板,这不是我们要做的工作(在这个问题)。动态多态性:变量的指针(引用)在C++基类类型可以引用任何派生类除了精确匹配变量类型的对象类型的对象。这允许数组和其他类型的容器将指针指向不同类型的对象。因为在运行时变量的赋值通常发生,这必然是一个运行时现象。C++还提供了一个dynamic_cast算子,使程序安全地尝试一个对象转换为一个更具体的对象类型的对象(而不是转换到一个更一般的类型,这是允许的)。此功能依赖于运行时类型信息(RTTI)。对象是某一特定类型也可以投,static_cast型,一个纯粹的编译时间构建没有运行时的开销,不需要RTTI。通常,当一个函数在派生类中重写基类中的函数,调用函数的对象的类型确定。一个给定的函数重写时存在的数量或功能的两个或两个以上的定义之间的参数类型没有区别。因此,在编译时,它可能不能够确定对象的类型,因此正确的函数调用,只给出一个基类的指针;因此,该决定是在运行时被关闭的。这就是所谓的动态调度。虚拟成员函数或方法[ 43 ]允许被调用的函数的最具体的实现,根据对象的实际运行时类型。在C++的实现,这是通常使用的虚拟函数表。如果对象的类型是已知的,这可能被绕过的前面加上一个完全限定类名前的函数调用,但一般调用虚函数在运行时确定。
除了标准的成员函数、运算符重载和析构函数可以是虚的。作为一个经验法则,如果任何类中的函数是虚函数,析构函数应该一样。作为对象的类型,在编译时,构造函数和扩展复制构造函数不能是虚的。然而,当指向派生对象的指针被传递为基类对象的指针时,可能会出现一个对象的副本。在这种情况下,一般的解决方案是创建一个()(或类似的)虚拟函数,创建并返回一个拷贝的派生类调用时。成员函数也可以用“纯虚拟的“附加它= 0右括号后的分号。一类包含纯虚函数称为抽象数据类型。不能从抽象数据类型中创建对象,它们只能来自于。任何派生类继承了虚函数为纯,并且必须提供一个非纯定义,它(和所有其他纯虚拟函数)在派生类的对象可以创建。试图创建一个类的对象的一个程序,一个纯虚拟成员函数或继承的纯虚拟成员函数是不成立的。
共有7个文件:
Collection.hpp
#ifndef COLLECTION_H_
#define COLLECTION_H_
typedef int E;
class Collection {
public:
Collection() {}
virtual ~Collection(){};
virtual void add(E e) = 0;
virtual void clear(void) = 0;
virtual bool contain(E e) = 0;
virtual bool isEmpty(void) = 0;
virtual void remove(int e) = 0;
virtual int size(void) = 0;
};
#endif
List.hpp
#ifndef LIST_H_
#define LIST_H_
#include <iostream>
#include "Collection.hpp"
class List : virtual public Collection {
public:
List() {}
virtual ~List() {}
virtual E& operator[](int index) = 0;
virtual E& get(int index) = 0;
virtual int indexOf(E element) = 0;
virtual void sort(void) = 0;
};
#endif
Linkedlist.hpp
#ifndef LINKEDLIST_H_
#define LINKEDLIST_H_
#include "List.hpp"
#include <iostream>
class LinkedList : virtual public List {
public:
typedef struct node {
E data;
struct node* next;
struct node* prev;
node(E data, struct node* next = NULL, struct node* prev = NULL)
: data(data), next(next), prev(prev) {}
} node;
LinkedList();
~LinkedList();
virtual void add(E e);
virtual void clear(void);
virtual bool contain(E e);
virtual bool isEmpty(void);
virtual void remove(E e);
virtual E& operator[](int index);
virtual E& get(int index);
virtual int indexOf(E element);
virtual void sort(void);
virtual int size(void);
private:
node* head;
node* tail;
int _size;
};
#endif
Linkedlist.cpp
#include "LinkedList.hpp"
#include <iostream>
LinkedList::LinkedList() : head(NULL), tail(NULL), _size(0) {}
LinkedList::~LinkedList() { this->clear(); }
void LinkedList::add(E e) {
if (tail == NULL) {
this->head = this->tail = new node(e);
} else {
this->tail->next = new node(e, NULL, tail);
tail = tail->next;
}
this->_size++;
}
void LinkedList::clear(void) {
node* p = this->head;
while (p != NULL) {
node* next = p->next;
delete p;
p = next;
}
this->head = this->tail = NULL;
this->_size = 0;
}
bool LinkedList::contain(E e) {
node* p = this->head;
while (p != NULL) {
if (p->data == e) {
return true;
}
p = p->next;
}
return false;
}
bool LinkedList::isEmpty(void) { return this->_size == 0; }
void LinkedList::remove(E e) {
node* p = this->head;
while (p != NULL) {
if (p->data != e) {
p = p->next;
} else {
if (p == this->head) {
this->head = this->head->next;
if (this->head != NULL) {
this->head->prev = NULL;
}
delete p;
p = head;
} else if (p == this->tail) {
tail = tail->prev;
tail->next = NULL;
delete p;
p = NULL;
} else {
p->next->prev = p->prev;
p->prev->next = p->next;
node* temp = p;
p = p->next;
delete temp;
}
this->_size--;
}
}
}
E& LinkedList::operator[](int index) { return this->get(index); }
E& LinkedList::get(int index) {
node* p = this->head;
int counter = 0;
while (p != NULL) {
if (counter == index) {
return p->data;
}
counter++;
p = p->next;
}
return *reinterpret_cast<E*>(NULL);
}
int LinkedList::indexOf(E element) {
node* p = this->head;
int index = 0;
while (p != NULL) {
if (p->data == element) {
return index;
} else {
p = p->next;
index++;
}
}
return -1;
}
int LinkedList::size(void) {
return this->_size;
}
void LinkedList::sort(void) {
if (this->size() > 1) {
node* fast = this->head;
node* slow = this->head;
LinkedList li_left;
LinkedList li_right;
li_left.head = this->head;
while (fast != NULL && fast->next != NULL) {
li_left._size++;
fast = fast->next->next;
slow = slow->next;
}
li_left.tail = slow->prev;
li_left.tail->next = NULL;
li_right.head = slow;
li_right.head->prev = NULL;
li_right.tail = this->tail;
li_right._size = this->_size - li_left._size;
this->head = NULL;
this->tail = NULL;
li_left.sort();
li_right.sort();
node* pointer_left = li_left.head;
node* pointer_right = li_right.head;
node* pointer_head = NULL;
node* pointer_tail = NULL;
while (pointer_left != NULL && pointer_right != NULL) {
node* temp;
if (pointer_left->data <= pointer_right->data) {
temp = pointer_left;
pointer_left = pointer_left->next;
} else {
temp = pointer_right;
pointer_right = pointer_right->next;
}
if (pointer_head == NULL) {
pointer_head = pointer_tail = temp;
} else {
pointer_tail->next = temp;
temp->prev = pointer_tail;
pointer_tail = temp;
}
pointer_head->prev = NULL;
pointer_tail->next = NULL;
}
while (pointer_left != NULL) {
pointer_tail->next = pointer_left;
pointer_left->prev = pointer_tail;
pointer_tail = pointer_left;
pointer_left = pointer_left->next;
}
while (pointer_right != NULL) {
pointer_tail->next = pointer_right;
pointer_right->prev = pointer_tail;
pointer_tail = pointer_right;
pointer_right = pointer_right->next;
}
this->head = pointer_head;
this->tail = pointer_tail;
li_left.head = li_left.tail = NULL;
li_right.head = li_right.tail = NULL;
}
}
Arraylist.hpp
#ifndef ARRAYLIST_H_
#define ARRAYLIST_H_
#include "List.hpp"
class ArrayList : public List {
public:
ArrayList();
~ArrayList();
virtual void add(E e);
virtual void clear(void);
virtual bool contain(E e);
virtual bool isEmpty(void);
virtual void remove(E e);
virtual E& operator[](int index);
virtual E& get(int index);
virtual int indexOf(E element);
virtual void sort(void);
virtual int size(void);
private:
E* storage;
int _size;
int _maxsize;
static const int extend_factor = 2;
void extend(void);
};
#endif
Arraylist.cpp
#include "ArrayList.hpp"
#include <algorithm>
ArrayList::ArrayList() {
this->storage = new E[65536]();
this->_size = 0;
this->_maxsize = 65536;
}
void ArrayList::extend(void) {
int new_size = _maxsize * extend_factor;
E* new_storage = new E[new_size]();
for (int i = 0; i < this->_size; i++) {
new_storage[i] = this->storage[i];
}
delete[] storage;
storage = new_storage;
_maxsize = new_size;
}
ArrayList::~ArrayList() {
if (storage != NULL) {
delete[] storage;
}
}
void ArrayList::add(E e) {
if (this->_size + 1 > this->_maxsize) {
extend();
}
storage[this->_size] = e;
_size++;
}
void ArrayList::clear(void) {
delete this->storage;
storage = new E[16]();
_size = 0;
_maxsize = 16;
}
bool ArrayList::contain(E e) {
for (int i = 0; i < this->_size; i++) {
if (this->storage[i] == e) {
return true;
}
}
return false;
}
bool ArrayList::isEmpty(void) { return (this->_size == 0); }
void ArrayList::remove(E e) {
for (int i = 0; i < this->_size;) {
if (this->storage[i] == e) {
for (int j = i + 1; j < this->_size; j++) {
this->storage[j - 1] = this->storage[j];
}
this->_size--;
} else {
i++;
}
}
}
E& ArrayList::operator[](int index) { return this->storage[index]; }
E& ArrayList::get(int index) { return this->storage[index]; }
int ArrayList::indexOf(E element) {
for (int i = 0; i < this->_size; i++) {
if (this->storage[i] == element) {
return i;
}
}
return -1;
}
int ArrayList::size(void) { return this->_size; }
static void swap(int* a, int* b) {
if (a != b) {
*a = *a ^ *b;
*b = *a ^ *b;
*a = *a ^ *b;
}
}
static int partion(int* A, int from, int to) {
// A[to] is the pivot
int i = from, j = from - 1;
for (; i < to; i++) {
if (A[i] < A[to]) {
j++;
swap(&A[i], &A[j]);
}
}
swap(&A[j + 1], &A[to]);
return j + 1;
}
/*
static int random_partion(int * A, int from, int to) {
int r = getRandeomNum(from, to);
swap(&A[r], &A[to]);
return partion(A, from, to);
}
*/
static void qsort(int* A, int from, int to) {
if (to > from) {
int middle = partion(A, from, to);
qsort(A, from, middle - 1);
qsort(A, middle + 1, to);
}
}
void ArrayList::sort(void) { qsort(this->storage, 0, this->_size - 1); }
main.cpp
#include <iostream>
#include <cstdlib>
#include "Collection.hpp"
#include "List.hpp"
#include "LinkedList.hpp"
#include "ArrayList.hpp"
#include <exception>
using std::cin;
using std::cout;
using std::endl;
using std::exception;
class AlgorithmnForbidden : public exception {
virtual const char *what() const throw() {
return "Please do not use std::sort or std::list or std::vector .....";
}
};
class TEST {
private:
int *testData;
int data_size;
public:
TEST() {
#if defined(_GLIBCXX_ALGORITHM) || defined(_GLIBCXX_LIST) || \
defined(_GLIBCXX_VECTOR)
//throw AlgorithmnForbidden();
cout << "please do not use algorithm" << endl;
#endif
cin >> data_size;
cout << "test data size:" << data_size << endl;
testData = new int[data_size];
for (int i = 0; i < data_size; i++) {
cin >> testData[i];
}
}
~TEST() { delete[] testData; }
void test_List(Collection *c) {
cout << (c->isEmpty() ? "true" : "false") << endl;
int n = data_size;
for (int i = 0; i < n; i++) {
c->add(testData[i]);
}
reinterpret_cast<List *>(c)->sort();
for (int i = 0; i < n; i++) {
cout << (*reinterpret_cast<List *>(c))[i] << " ";
}
cout << endl;
// not empty
cout << (c->isEmpty() ? "true" : "false") << endl;
for (int i = 0; i < n / 2; i++) {
cout << "(" << (c->contain(i) ? "true" : "false");
cout << ","
<< (reinterpret_cast<List *>(c)->indexOf(i) != -1 ? "true" : "false")
<< ") ";
c->remove(i);
}
cout << endl;
for (int i = 0; i < c->size(); i++) {
cout << (*reinterpret_cast<List *>(c))[i] << " ";
}
cout << endl;
}
void test_ArrayList() {
Collection *c = new ArrayList();
test_List(c);
delete c;
}
void test_LinkedList() {
Collection *c = new LinkedList();
test_List(c);
delete c;
}
void runAllTests() {
cout << "Testing ArrayList:" << endl;
test_ArrayList();
cout << endl;
cout << "Testing LinkedList:" << endl;
test_LinkedList();
}
};
int main() {
TEST t;
t.runAllTests();
return 0;
}