创建一个类以提供列表接口

3

我正在尝试创建一个可在库中使用的类,但我不确定是否可以做到。这个类的想法是提供在列表中插入、搜索和删除项目的方法,但我的主要问题是,由于我不知道要放置在列表中的对象类型,我不知道如何处理它。我认为我可以放置一个void指针,然后使它指向一个结构体,但我无法使其工作。

假设我的类是这样的:

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的结构体。尽管如此,我希望我的类适用于任何类型的结构体。 我不知道我是否准确地解释了我想做的事情,我尝试了几种方法,但都失败了。
如果我没有正确解释,请看下面的代码,了解我希望这个类如何工作。
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*/

有人能指点我如何使一个类与结构一起工作,而不知道结构的类型吗?
提前谢谢。

你有研究过模板类吗? - alacy
模板可能是您正在寻找的。您可以使用模板参数T创建一个模板类,而不是使用void *,您可以使用正确的类型(即T)。 - 463035818_is_not_a_number
模板确实很有用。此外,尽量避免使用那些新的东西。 ListManager *Worker; 变成:ListManager worker; 等等。 - dau_sama
1
为什么不直接使用优秀的 std::vectorstd::list - Gábor Angyal
我还没有考虑模板,我一直在尝试一种更复杂的方法,我会尝试一下的,谢谢你的评论。 - user2946417
显示剩余3条评论
4个回答

1

你需要模板!这里有一个简单的界面,可以让你开始工作。

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

现在 T 是你的类型,你需要这样声明一个 ListManager:
ListManager<Employee> manager;

我建议你也看一下STL文档/实现的列表: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

实际上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> {
  // ...
};

当然,这只是一个基本的例子,你真的应该在remove()get()方法中进行一些检查。


3
“在C++中真的没有接口”... 不带数据成员的纯抽象类按定义算不算接口? - 463035818_is_not_a_number
我的观点是它仍然是一个类,没有像Java中那样的“interface”关键字。 - dtech
抱歉有些挑剔,但是例如在C++中也没有abstract关键字,但是绝对存在抽象类(当然它们也是“类”,但是为它们命名完全有意义)。 - 463035818_is_not_a_number
1
C++中没有“abstract”关键字,但是有T foo() = 0这个语法,它相当于C++中的“abstract”关键字。 - dtech

0

这个问题有多种解决方案。

可以简单地使用 std::list。

std::list<Employee> manager;

如果第一种方法不可行,您可以使用模板定义自己的列表接口。
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 不可行,因为您需要在列表中使用多个类型。您可以使用 Any 列表(例如 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;
               }
         }
     }
};

代码未经测试


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接