Как реализовать двусвязный список, который содержит целые и пустые указатели? - PullRequest
0 голосов
/ 10 февраля 2020

Я пытаюсь реализовать свою собственную версию общих структур данных для улучшения моего кодирования. У меня есть задание, которое требует двусвязного списка, который может содержать int и указатели void, void * data. Моя структура имеет два типа элементов: один для 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
};

Вот моя структура Node и двунаправленный класс списка. Я был в состоянии написать все методы, которые обрабатывают int. Моя путаница заключается в том, чтобы взять указатель void в качестве параметра и добавить его в тот же связанный список со значениями int.

Я понимаю, что указатель void - это указатель, который может указывать на любые данные, но я не понимаю, как мне взять указатель void в качестве параметра и добавить его в тот же связанный список, который я инициализировал этим конструктором:

LL::LL() {
    head = nullptr;
    tail = nullptr;
    size = 0;
}

Вот мои функции добавления, где я была идея перегрузки, так что если бы параметр был указателем, данные были бы добавлены как 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 / еще, чтобы определить, нужно ли печатать int или печатать void* pntData.

Пожалуйста, укажите мне правильное направление.

1 Ответ

1 голос
/ 10 февраля 2020

Согласно вашим комментариям вы хотите printLL() напечатать объект, на который указывает указатель void*.

Это невозможно. Указатель void* не имеет информации о типе, на который он указывает, поэтому вы не можете разыменовать указатель.

Если вы хотите сделать это, вам нужно сохранить дополнительный указатель на функцию-обработчик в Node, что printLL() будет вызывать для каждого Node для печати его 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);
    //...
}

У меня такое ощущение, что это это не то, что упражнение намеревается сделать, но, как я сказал в комментариях, оно не имеет смысла для меня, во-первых.

...