C++ 如何实现包含整数和空指针的双链接列表?

C++ 如何实现包含整数和空指针的双链接列表?,c++,linked-list,void-pointers,C++,Linked List,Void Pointers,我正在尝试实现我自己版本的通用数据结构,以改进我的编码。我有一个作业,它需要一个双链接列表,可以保存int和void指针,void*data。My struct有两种成员类型,一种用于int,另一种用于void* struct Node { int data; void* pntData; Node* next; Node* previous; }; class LL { private: Node* head; Node* tail; i

我正在尝试实现我自己版本的通用数据结构,以改进我的编码。我有一个作业,它需要一个双链接列表,可以保存
int
和void指针,
void*data
。My struct有两种成员类型,一种用于
int
,另一种用于
void*

struct Node {
    int data;
    void* pntData;
    Node* next;
    Node* previous;
};
class LL {
private:
    Node* head;
    Node* tail;
    int size;
public:
    LL();
    void insert_front(int data);
    void insert_front(void* data);//overloaded for void pointer data types
    void printLL();//removed unrelated methods
};
这是我的节点结构和双链表类。我已经能够编写所有处理
int
的方法。我的困惑在于将一个空指针作为参数,并将其添加到具有
int
值的同一个链表中

我知道空指针是一个可以指向任何类型数据的指针,但我不知道应该如何将空指针作为参数,并将其添加到使用此构造函数初始化的同一个链表中:

LL::LL() {
    head = nullptr;
    tail = nullptr;
    size = 0;
}
这里是我的append函数,在这里我想到了重载,如果参数是指针,那么数据将作为
void*pntData
添加到我的类变量中。如果参数是int,那么数据将作为
int
添加到我的类变量中

void LL::insert_front(int data) {
    Node* temp = new Node();
    if (head == nullptr) {
        head = temp;
        temp->previous = nullptr;
        temp->next = nullptr;
        temp->data = data;
        tail = temp;
    }
    else {
        temp->previous = nullptr;
        temp->next = head;
        temp->data = data;
        head->previous = temp;
        head = temp;
    }
    size++;
}

void LL::insert_front(void* data) {
    Node* temp = new Node();
    if (head == nullptr) {
        head = temp;
        temp->previous = nullptr;
        temp->next = nullptr;
        temp->pntData = data;
        tail = temp;
    }
    else {
        temp->previous = nullptr;
        temp->next = head;
        temp->pntData = data;
        head->previous = temp;
        head = temp;
    }
    size++;
}
问题可能出在我的
printLL()
函数中,它可能需要一个if/else来确定是否需要打印
int
,或者是否需要打印
void*pntData


请给我指出正确的方向。

根据您的注释,您希望
printLL()
打印
void*
指针指向的对象

这是不可能的。
void*
指针没有关于它所指向的类型的信息,因此无法取消对指针的引用

如果要执行此操作,则需要在
节点
中存储指向处理程序函数的附加指针,
printLL()
将调用每个
节点
打印其
void*
。然后,您需要在指针类型上创建
insert.*
函数模板,以便为提供的类型找出要存储的正确函数指针,即:

struct Node {
    int data;
    void* pntData;
    Node* next;
    Node* previous;
    void(*print)(void*) = nullptr; // Initialize with null pointer to indicate that no `void*` is stored.
};

//...

template<typename T>
void LL::insert_front(T* data) {
    Node* temp = new Node();
    //...
    temp->print = [](void* ptr){
        if(ptr != nullptr)
            std::cout << *static_cast<T*>(ptr);
        else
            // What to do if we stored a null pointer for `void*`
    };
    //...
}

//...

void LL::printLL() {
    //...
    if(node->print != nullptr)
        node->print(node->pntData);
    //...
}
struct节点{
int数据;
void*pntData;
节点*下一步;
节点*先前;
void(*print)(void*)=nullptr;//使用空指针初始化以指示未存储“void*”。
};
//...
模板
void LL::insert_front(T*数据){
Node*temp=新节点();
//...
临时->打印=[](无效*ptr){
如果(ptr!=nullptr)
std::cout print!=nullptr)
节点->打印(节点->pntData);
//...
}

我有一种感觉,这不是该练习打算让你做的,但正如我在评论中所说的,它首先对我来说没有意义。

正确的方向因为你将是一本C++的书,它涵盖了现代C++;特别是关于如何使用<代码> STD::变体< /Cord>模板,它完成了你要问的内容。它将使程序变得简单得多,就像只需要一个代码>插入式前/ <代码>(),而不是痛苦的代码复制。阅读后,经过一些练习,您应该能够完成此“在线作业”。祝你好运!我认为在值类型上设置链接列表模板可能更有教育意义,即编写一个包含
节点
类的泛型
链接列表
。然后,你可以使用包含整数的链接列表,和(分别)void指针。这似乎不是一个好的练习。如果不存储指针指向的类型的信息,则在容器中存储
void*
指针是没有意义的,但这是一项相当困难的任务,实际上您只需使用
std::variant
或(很少)
std::any
改为类型泛型容器的元素类型。您希望看到什么
printLL()
如果元素是一个
void*
,则打印?指针中存储的地址或指针指向的对象?是否希望列表接受空指针作为有效值来存储
void*
?虽然我同意您的意见,但这是我必须遵循的赋值。因此,我无法将空指针存储在节点结构中不同时存储类型?列表应包含整数和指针。您可以根据需要添加其他类型。包括以下成员函数:void insert_front(int data);void insert_front(void*data);void insert_rear(int data);void insert_rear(void*data);int remove_front_i();void*remove_front_p();int remove_real_i();void*remove_real_p();int empty();使用动态内存。使用“新建”插入时分配内存的指令和删除时返回内存的delete指令。@Suede和
printLL
的规范是什么?这是指令,您的答案看起来非常有用。我将在晚饭后不久返回。非常感谢您的帮助,空指针让我感到困惑在Suede C++中几乎不需要< C++ >代码> java >。这在C.是很常见的,这就是为什么练习是如此混乱的。它不是C++是如何正常编写的。如果你不需要<代码> PrtLL</代码>,如果该列表只需要用它给出的相同指针类型来工作,那么你就不需要我在答案中所写的内容。t是
printl
函数(或需要该类型的任何其他函数)如果你不需要这个函数,那么你可以只存储一个附加的<代码>布尔O/S>来指示你是否存储了一个<代码> int <代码>或<代码> Value*/Cuff>。@ SueDe这是很不幸的。在某个点上,把C++作为C的扩展是有意义的,但是现代C++的习惯风格是非常不同的。来自C的ENT,如果从一开始就教C或者实际的C++,那就更好了,因为两者混合使一切都变得不必要的复杂,就像你在这里看到的一样。