Задача на классы - Наследование, виртуальные методы и прочая прелесть

условие:

2.	Библиотека работы с множествами (2 студента, максимум – 100 баллов)
Разработать библиотеку обобщенных классов для работы с множествами данных.
 В структуру классов входят как минимум:
•	ISet<T>: IEnumerable<T> – базовый интерфейс для всех списков;
o	методы:
	void Add(T value);
	void Clear();
	bool Contains(T value);
	void Remove(T value);
o	свойства:
	int Count;
	bool isEmpty;
•	SetException – класс, описывающий исключения, которые могут происходить в ходе работы с множествами 
(также можно написать ряд наследников от SetException);
•	ArraySet<T>: ISet<T> – класс множества на основе массива;
•	LinkedSet<T>: ISet<T> – класс множества на основе связанного списка;
•	HashSet<T>: ISet<T> – класс множества на основе алгоритма хеширования 
(использовать методы GetHashCode и Equals типа T);
•	UnmutableSet<T>: ISet<T> – класс неизменяющегося множества, 
является оберткой над любым существующим множеством 
(должен кидаться исключениями на вызов любого метода, изменяющего множество);
•	SetUtils – класс различных операций над множеством;
o	методы:
	static bool Exists<T>(ISet<T>, CheckDelegate<T>);
	static ISet<T> FindAll<T>(
ISet<T>, CheckDelegate<T>, SetConstructorDelegate<T>);
	static ISet<TO> ConvertAll<TI, TO>(
ISet<TI>, ConvertDelegate<TI, TO>, SetConstructorDelegate<TO>);
	static void ForEach(ISet<T>, ActionDelegate<T>);
	static bool CheckForAll<T>(ISet<T>, CheckDelegate<T>);
	свойства:
	static readonly SetConstructorDelegate<T> ArraySetConstructor;
	static readonly SetConstructorDelegate<T> LinkedSetConstructor;
	static readonly SetConstructorDelegate<T> HashSetConstructor;
Также необходимо разработать серию примеров, демострирующих основные аспекты 
работы с данной библиотекой множеств.
baton's picture

1) произвольное множество и методы работы с ним опишем с помощью базового класса и его наследников (наследники - для различных типов данных, содержащихся в множестве - для которых придется менять часть методов).
2) само множество может представлять собой линейный список (необходимо когда данные разных типов в одном множестве) или массив (для одного типа). наверно, терпения у меня не хватит и я сделаю только с массивом.
3) методы, которые будут меняться в наследниках, объявим виртуальными.
о виртуальных методах и полиморфизме: http://programmersclub.ru/38/
про статические методы и элементы : http://www.c-cpp.ru/books/staticheskie-c...

vedro-compota's picture

множества вполне могут быть реализованы на основе массивов.

_____________
матфак вгу и остальная классика =)

baton's picture

это мне известно)) так я и собираюсь сделать - так проще
но препод поощряет создание еще одной реализации - по спискам.
по условию вообще надо и так и этак...
базовый класс (чьи интерфейсные методы будут наследоваться классами конкретных вариантов множеств) построен на следующем скелете:

template<typename T>
class ISet{  /// отеческий класс для всех последующих

public:	///////// объявление методов

	virtual void Add(){  // добавить элемент к множеству
	};

	virtual void Clear(){      // очистить множество
	};

	virtual bool Contains(){   // вывод содержимого
	};

	virtual void Remove(){   //  удалить элемент
	};

	bool isEmpty(){     //проверка на пустоту
	};

	virtual void show_mnojestvo () {   //вывод множества на экран
	};

private:
	new T = T A; //  массив элементов множества
};

про непонятную конструкцию типа template и про шаблончики читаем тут http://programmersclub.ru/29/

baton's picture

для начала я решил сделать все это в одном классе на массиве - без всяких виртуалок и наследования - дабы мозги излишне не грузить всей задачей сразу и потренироваться.
код класса:



class ISet{  ///  класс содержащий базовые интерфейсные функции

private:
	//int A[5];
	int *B; // динамический  массив элементов множества

public:	
	int i;
	///////// объявление методов
	void create(int *B){ 
		cin >> i; //ввод размера массива
		int *B = new int [i]; //выделение памяти под массив
		for(int j = 0; j < i; j++){  //заполнение его нулями
			B[j]  = 0;
		}
	};

	void Add(int *B){  // добавить элемент к множеству
		int j = 0; // счетчик цикла вайл
		while(j < i){  //значение счетчика не превышает размер массива
			if(B[j] != 0)  // если элемент не равен нулю , то идем дальше
				j++;
			else   // иначе - нуль - ячейка пуста - добавить значение
				cin >> B[j];
					break; // выход
//потом напишу пересоздание массива размерности i+1,
// если добавляемый элемент не помещается в старую размерность
		}
	};

	void Clear(int *B){      // очистить множество - по сути то же обнуление
			for(int j = 0; j < i; j++){
			B[j]  = 0;
		}
	};

	bool Contains(int *B){   // вывод содержимого
		cout << "множество содержит следующие элементы:";
		for(int j = 0; j < i; j++){
			cout << "№" << j << ")  " << B[j] << endl;
		}
		cout << "конец множества";

	};

	void Remove(int *B, int b){   //  удалить элемент 
        // в списке параметров функции - массив и номер удаляемого элемента
	  if(b <= i && b >= 0){  // если номер удаляемого элемента 
//не больше размера массива и не меньше нуля, то
		int * A = new int[b];  //создаем массив, в который поместим все элементы, 
//стоящие за удаляемым
//потом добавлю условие, что если элемент последний, то его просто обнулить
		B[b];
		for(int j = b+1; j < i; j++){ //все элементы после удаляемого пишем в массив А
			int q = 0;
			A[q] = B[j];
			q++;
		}

		for(int j = b; j < i; j++){ // а потом перезаписываем их в В
			int q = 0;
			B[j] = A[q];
			q++;
		}
// потом допишу обнуление последнего элемента -
// ведь массив становится короче на один элемент, 
//а писать сюда цикл обнуления всего что стоит за удаляемым -  мне лень
	  }
	  else 
// если номер удаляемого элемента меньше нуля или такого номера нет, то
		  cout << "некорректное значение номера эллемента";
	};

	bool isEmpty(int *B){     //проверка на пустоту
		for(int j = 0; j < i; j++){
			if( B[j]  != 0)
				//break;
				return true;
		}
		return false;
	};
};



конкретно в этом куске кода у меня ошибка такого типа:
"...klass_ example\klass_ example\klass.h(16): error C2082: переопределение формального параметра "B" ..."

void create(int *B){ 
		cin >> i; //ввод размера массива
		int *B = new int [i]; //выделение памяти под массив
		for(int j = 0; j < i; j++){  //заполнение его нулями
			B[j]  = 0;
		}
	};
baton's picture

в процессе буду дописывать и редактировать

#include <cstdio>
#define _USE_MATH_DEFINES
#include <cmath>
#include <string>
#include <conio.h>
#include <iostream>
#include <ctime>

using std::cout;
using std::cin;
using std::endl;
using namespace std;

struct point{
		point * previous;
		int a;
		point * next;
	};

void add_before(point* &head, int n){
}

void creater(point* &head, int n, int N ){
	int x = rand() % 100;
	add_before(head, x);
	printf("%d ", x);
	for (int i=1; i<=n; i++)
	{	
		x = rand() % 100;
		add_before(head, x);
		printf("%d ", x);
	}
}

bool chek_empty(){
}

void deleter(){
}

void main() {
	setlocale(LC_ALL, "Russian");




	getch();
}

это уже будет реализация через списки

baton's picture

ннннннннннн