【问题标题】:Making a class to provide Lists interface制作一个类来提供 Lists 接口
【发布时间】:2015-06-27 03:58:24
【问题描述】:

我正在尝试创建一个在库中使用的类,但我不确定它是否可以做到。此类的想法是提供在列表中插入、搜索和删除项目的方法,但我的主要问题是,由于我不知道要放置在列表中的对象的类型,所以我不知道如何使用它。我以为我可以放置一个 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*/

有人能指出我正确的方向吗,例如如何在不知道结构类型的情况下使课程与结构一起工作?

提前致谢

【问题讨论】:

  • 你研究过模板类吗?
  • 模板可能是您正在寻找的。您将使用模板参数T 创建一个模板类,而不是使用void*,您可以使用正确的类型(即T
  • 确实是模板。另外,尽量避免所有这些新的。 ListManager *工人;变为:ListManager 工作者;等等
  • 为什么不直接使用优秀的std::vector,或者std::list
  • 使用mapvector。如果您想隐藏实施细节,请为其创建一个类。

标签: c++ list class


【解决方案1】:

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

只需使用 std::list

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;
               }
         }
     }
};

代码未经测试

【讨论】:

    【解决方案2】:

    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() 方法。

    【讨论】:

    • "C++ 中真的没有接口" ..不是没有数据成员的纯抽象类定义的接口吗?
    • 我的意思是它仍然是一个类,没有像说Java那样的interface关键字。
    • 抱歉扯淡了,但也没有abstract这样的关键字,但是C++中肯定有抽象类(当然它们也是“只是类”,但完全有道理为它们命名)
    • 没有abstract关键字,但是有T foo() = 0,这是C++的abstract关键字。
    【解决方案3】:

    请参阅本教程: 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

    【讨论】:

      【解决方案4】:

      您需要模板! 这是一个简单的界面,您可以开始使用。

      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/ 您还需要深入研究迭代器的概念。 另外,尝试使用值而不是指针。使用我给您的接口,您可以将实际值存储在列表中,而不是指针,因此列表拥有对象,您无需手动管理内存。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-03-18
        • 1970-01-01
        • 1970-01-01
        • 2011-05-11
        • 1970-01-01
        • 2023-03-09
        • 1970-01-01
        • 2017-02-21
        相关资源
        最近更新 更多