2015-04-20 2 views
3

Я пытаюсь сделать класс для использования в библиотеке, и я не уверен, что его даже можно сделать. Идея этого класса заключается в том, чтобы предоставить методы для вставки, поиска и удаления элементов в списке, но моя основная проблема заключается в том, что, поскольку я не знаю тип объекта, который я хочу разместить в списке, я не знаю, как работать с ним. Я думал, что могу разместить указатель на пустоту, а затем указать на структуру, но я не смог заставить ее работать.Создание класса для представления интерфейса списков

Давайте предположим, мой класс что-то вроде этого:

class ListManager 
{ 
    private: 
     void* FirstItem;//This would point to the first item of the list 
     void* LastItem;//This would point to the last item of the list 
    public: 
     void AddItemToList(void* Item); 
     void RemoveItemFromList(void* Item); 
} 

Таким образом, идея была в том, что, с моей программы, я могу определить структуру, как

struct Employee 
{ 
    *char Name; 
    int Id; 
    int PhoneNumber; 
} 

И затем, используйте этот класса, чтобы иметь возможность добавлять/удалять сотрудников. Поэтому в этом случае указатели void * должны указывать на структуру типа Employee. Тем не менее, я хочу, чтобы мой класс работал для любого типа структуры. Я не знаю, правильно ли я объяснил, что хочу, я попробовал несколько способов сделать это и потерпел неудачу на всех из них.

Im собирается разместить код, как я хотел бы класс работать, если я нету объяснил себя правильно

ListManager *Worker; 
Worker=new(ListManager); 

Employee *Item; 
Item=new (Employee); 

Item->Id=126; 
Item->PhoneNumber=42154872; 

Worker->AddItemToList(Item); 
/*At this point, FirstItem and LastItem should point to the Item i just created*/ 

Может кто-то мне точку в правильном направлении, как сделать работу класса с структуру, не зная тип структуры?

Заранее спасибо

+0

вы смотрели на классы шаблонов ли? –

+0

шаблоны, вероятно, то, что вы ищете. Вы сделали бы шаблонный класс с параметром шаблона 'T', и вместо использования' void * 'вы могли бы использовать правильные типы (например,' T') – user463035818

+0

шаблонов. Также старайтесь избегать всех новых. ListManager * Рабочий; становится: ListManager worker; и т. д. –

ответ

1

Вам нужны шаблоны! вот простой интерфейс, с которым вы можете начать работать.

template <typename T> 
class ListManager 
{ 
    public: 
     void addItemToList(const T& item); 
     void removeItemFromList(const T& item); 
} 

Теперь T ваш тип, и вы бы объявить ListManager так:

ListManager<Employee> manager; 

Я хотел бы предложить вам также посмотреть на СТЛ документации/реализации перечня по адресу: http://www.cplusplus.com/reference/list/list/ У вас также есть понятие итераторов, чтобы вникать в. Кроме того, попробуйте использовать значения вместо указателей. С помощью интерфейса, который я вам дал, вы сохранили бы фактическое значение в списке, а не указатель, поэтому список принадлежит этому объекту, и вам не нужно будет управлять своей памятью вручную.

0

Смотрите этот учебник: http://www.tutorialspoint.com/cplusplus/cpp_templates.htm

Ваш пример может быть выглядеть следующим образом:

#include <iostream> 
using namespace std; 

template <class T> 
class ListManager 
{ 
    private: 
     void* FirstItem;//This would point to the first item of the list 
     void* LastItem;//This would point to the last item of the list 
    public: 
     void AddItemToList(const T& Item){ 
      std::cout << Item << std::endl; 
     }; 
     void RemoveItemFromList(const T& Item){}; 
}; 

int main() { 
    ListManager<std::string> mgr; 
    mgr.AddItemToList("Test"); 
    return 0; 
} 

Выход:

Test 

Рабочий пример: http://ideone.com/FCAtcJ

0

Там реак LLY нет интерфейсов в C++, но вы можете использовать шаблон класса точно так же:

template <typename T> 
class ListInterface { 
public: 
    void add(T * item) { list.push_back(item); } 
    void remove(T * item) { list.erase(std::find(list.begin(), list.end(), item)); } 
    T * get(int index) { return list[index]; } 
    int size() const { return list.size(); } 
private: 
    std::vector<T *> list; 
}; 

class Manager : public ListInterface<Employee> { 
    // ... 
}; 

Естественно, это пример Barebone, вы действительно сбился сделать некоторые проверки в remove() и get() методов.

+3

«На самом деле нет интерфейсов в C++». Разве чистый абстрактный класс без элементов данных по определению по интерфейсу? – user463035818

+0

Мое мнение, что это еще класс, нет ключевых слов 'interface', например, в Java. – dtech

+0

Извините за расщепление волосков, но, к примеру, также нет слова «абстрактного», но в C++ есть определенные абстрактные классы (конечно, они также являются «просто классами», но вполне разумно назвать их тем, чем они являются) – user463035818

0

Существует множество решений этой проблемы.

Просто используйте зЬй :: список

std::list<Employee> manager; 

Если 1. не возможно, вы можете определить свой собственный интерфейс списка с помощью шаблона

template <class T> 
class ListManager 
{ 
private: 
    class Iterator { 
    public: 
      T& item; 
      Iterator* next; 
      Iterator* prev; 
      Iterator(T& i, Iterator* n, Iterator* p) : item(i), next(n), prev(p) {} 
    } 
    Iterator* FirstItem = NULL;//This would point to the first item of the list 
    Iterator* LastItem = NULL;//This would point to the last item of the list 
public: 
    void AddItemToList(T& Item) { 
      if(LastItem) { 
       Iterator* it = new Iterator{Item, NULL, LastItem}; 
       LastItem->next = it; 
       LastItem = it; 
      } else { 
       Iterator* it = new Iterator{Item, NULL, NULL}; 
       FirstItem = it; 
       LastItem = it; 
      } 
    } 
    void RemoveItemFromList(const T& Item) { 
     for(Iterator* it = FirstItem; it != NULL; it = it->next) { 
       if(it->item == Item) { 
        if(it->prev) 
         it->prev->next = it->next; 
        else 
         FirstItem = it->next; 
        if(it->next) 
         it->next->pref = it->pref; 
        else 
         LastItem = it->pref; 
        delete it; 
        break; 
       } 
     } 
    } 
}; 

Если 1. и 2. не представляется возможным, потому что вы вам нужно несколько типов внутри вашего списка. Вы можете использовать список Anys (как boost::Any) или небезопасной версии с void*:

class ListManager 
{ 
private: 
    class Iterator { 
    public: 
      void* item; 
      Iterator* next; 
      Iterator* prev; 
      Iterator(void* i, Iterator* n, Iterator* p) : item(i), next(n), prev(p) {} 
    } 
    Iterator* FirstItem = NULL;//This would point to the first item of the list 
    Iterator* LastItem = NULL;//This would point to the last item of the list 
public: 
    template<class T> 
    void AddItemToList(T& Item) { 
      if(LastItem) { 
       Iterator* it = new Iterator{&Item, NULL, LastItem}; 
       LastItem->next = it; 
       LastItem = it; 
      } else { 
       Iterator* it = new Iterator{&Item, NULL, NULL}; 
       FirstItem = it; 
       LastItem = it; 
      } 
    } 
    template<class T> 
    void RemoveItemFromList(const T& Item) { 
     for(Iterator* it = FirstItem; it != NULL; it = it->next) { 
       if(it->item == &Item) { 
        if(it->prev) 
         it->prev->next = it->next; 
        else 
         FirstItem = it->next; 
        if(it->next) 
         it->next->pref = it->pref; 
        else 
         LastItem = it->pref; 
        delete it; 
        break; 
       } 
     } 
    } 
}; 

код не тестируется

Смежные вопросы