C++ 双向链表无法正常运行。错误 C2278

C++ Doubly Linked List not functioning correctly. Error C2278

嗨,过去几天我一直致力于制作一个双向链表,以便更好地 knowledge/insight 了解指针在 C++ 中的工作方式,但遇到了问题。程序本身已经完成并且应该可以运行,但是当我尝试编译它时出现错误。

已解决:错误 C2276:“!” : 对绑定成员函数表达式的非法操作

新问题:错误 LNK2019:未解析的外部符号 "public: __thiscall linked_list::node_t::node_t(double,struct linked_list::node_t *,struct linked_list::node_t *)" (??0node_t@linked_list@@QAE@NPAU01@0@Z) 在函数 [=28= 中引用] (?insert@linked_list@@QAEXNI@Z)

我似乎无法弄清楚问题出在哪里,恐怕我已经有了隧道视野,我希望能从你们那里得到建议。

h文件。

#include <iostream>

using namespace std;

class linked_list {
public:
    linked_list();
    ~linked_list();
    linked_list(const linked_list & src);
    linked_list & operator =(const linked_list & rhs);

    // Adds elements to the back.
    linked_list & operator +=(const linked_list & rhs);

    // inserting elements
    void insert(double value, size_t pos);

    // in front
    void push_front(double value);

    // in back
    void push_back(double value);

    // accessing elements
    double front() const;
    double back() const;
    double at(size_t pos) const;

    // removing elements
    void remove(size_t pos);

    // remove and access
    double pop_front();
    double pop_back();

    // informational
    size_t size() const;
    bool is_empty() const;

    // output
    void print() const;
    void print_reverse() const;

private:
    struct node_t {
        node_t(double value, node_t * next = 0, node_t * prev = 0);
        double value;
        node_t * next;
        node_t * prev;
    };
    node_t * head; // Points to the first element in the list.
    node_t * tail; // Points to the last element in the list.
    size_t lenght; // Counter of all the elements in the list.
};

Class 文件。

#include <iostream>
#include "LinkedList.h"

using namespace std;

linked_list::linked_list(){
    lenght = 0;
    head = nullptr;
    tail = nullptr;
}
linked_list::~linked_list(){
    while (head){
        node_t* ptr = head;
        head = head->prev;
        delete head;
    }
}
linked_list::linked_list(const linked_list & src){
    lenght = 0;
    head = nullptr;
    tail = nullptr;
    if (!src.is_empty()){
        node_t* ptr = src.head;
        while (ptr){
            push_back(ptr->value);
            ptr = ptr->next;
        }
    }
}
linked_list & linked_list::operator=(const linked_list & rhs){
    if (this != &rhs){
        if (!rhs.is_empty()){
            node_t* ptr = rhs.tail;
            while(ptr){
                push_front(ptr->value);
                ptr = ptr->next;
            }
        }
    }
    return* this;
}

// Adds Elements to the back.
linked_list &linked_list::operator+=(const linked_list & rhs){
    if (!rhs.is_empty()){
        node_t* ptr = rhs.tail;
        while (ptr){
            this->push_front(ptr->value);
            ptr = ptr->prev;
        }
    }
    return* this;
}

// Adds a new node at the chosen location.
void linked_list::insert(double value, size_t pos){
    if (!is_empty() && size() >= pos){
        node_t* ptr = head;
        int cnt = 0;
        while (cnt != pos){
            ptr = ptr->prev;
            cnt++;
        }
        node_t* insertNode = new node_t(value);
        node_t* nextNode = ptr->next;
        ptr->next = insertNode;
        insertNode->prev = ptr;
        nextNode->prev = insertNode;
        insertNode->next = nextNode;
    }
    else{
        cerr << "ERROR! The list is to empty or the position is too large/small.";
    }
}

// Adds a new node to the front.
void linked_list::push_front(double value){
    node_t* ptr = new node_t(value);

    // If list is empty.
    if (head == nullptr){
        head = ptr;
        tail = ptr;
    }
    // If list is not empty.
    else{
        head->next = ptr;
        ptr->prev = head;
        head = ptr;
    }
    lenght++;
}

// Adds a new node to the back.
void linked_list::push_back(double value){
    node_t* ptr = new node_t(value);

    // If list is empty.
    if (tail == nullptr){
        tail = ptr;
        head = ptr;
    }
    // If list is not empty.
    else{
        tail->prev = ptr;
        ptr->next = tail;
        tail = ptr;
    }
    lenght++;
}

// Accesses elements at the front.
double linked_list::front() const{
    return head->value;
}

// Accesses elements at the back.
double linked_list::back() const{
    return tail->value;
}

// Accesses elements at the chosen location.
double linked_list::at(size_t pos) const{
    if (!is_empty() && size() >= pos){
        node_t* ptr = head;
        int i = 0;
        while (ptr != nullptr){
            if (i == pos){
                return ptr->value;
            }
            ptr->prev;
            i++;
        }
    }
    else{
        cerr << "ERROR!The number you have is to too great or the list is empty.";
    }
    return NULL;
}

// Removes a node form the chosen location.
void linked_list::remove(size_t pos){
    if (!is_empty() && size() >= pos){
        if (pos == 0){
            pop_front();
        } else if (pos == size() - 1){
            pop_back();
        }
        else{
            node_t* ptr = head;
            int i = 0;
            while (ptr){
                // Changes the pointers next to node so they point to eachother then it removes the requested node.
                if (i == pos){
                    ptr->prev->next = ptr->next;
                    ptr->next->prev = ptr->prev;
                    delete ptr;
                    lenght--;
                    break;
                }
                else{
                    ptr->prev;
                    i++;
                }
            }
        }
    }
    else{
        cerr << "ERROR! The list is empty and therefore no elements can be removed.";
    }
}

// Removes a node form the front and returns its value.
double linked_list::pop_front(){
    // Checks if head is not empty or nullptr.
    if (head != nullptr && !is_empty()){
    double value = head->value;
    node_t* temptr = head;
    head = head->prev;
    head->next = nullptr;
    delete temptr;
    lenght--;
    return value;
    }
    // If head is empty or nullptr it prints the following.
    else{
        cerr << "ERROR! The list is empty";
        return NULL;
    }
}

// Removes a node form the back and returns its value.
double linked_list::pop_back(){
    // Checks if head is not empty or nullptr.
    if (head != nullptr && !is_empty()){
    double value = tail->value;
    node_t* temptr = tail;
    tail = tail->next;
    tail->prev = nullptr;
    delete temptr;
    lenght--;
    return value;
    }
    // If head is empty or nullptr it prints the following.
    else{
        cerr << "ERROR! The list is empty";
        return NULL;
    }
}

// Returns the size of the list.
size_t linked_list::size() const{
    return lenght;
}

// Checks if the list is empty or not.
bool linked_list::is_empty() const{
    if (lenght == 0){
        return true;
    }
    else{
        return false;
    }
}

// Prints the list from front to back.
void linked_list::print() const{
    if (!is_empty()){
        node_t* ptr = head;
        while (ptr){
            cout << ptr->value << "\n";
            ptr = ptr->prev;
        }
    } 
    else {
        cerr << "ERROR! The list is empty";
    }
}

// Prints from the list from back to front.
void linked_list::print_reverse() const{
    if (!is_empty()){
        node_t* ptr = tail;
        while (ptr){
            cout << ptr->value << "\n";
            ptr = ptr->next;
        }
    }
    else {
        cerr << "ERROR! The list is empty";
    }
}

主文件。

#include <iostream>
#include <time.h>
#include "LinkedList.h"

using namespace std;

void printList(linked_list list);

int main(){

    srand(time(0));

    linked_list list1, list2, list3, list4;

    // I fill the first two lists.
    for (int i = 0;i < 100; i++){
        list1.push_back(list1.back() + rand() % 20);
        list2.push_back(list2.back() + rand() % 20);
    }

    // Control which list has the highest value at 50 and then remove it.
    double value1 = list1.at(50);
    double value2 = list2.at(50);

    if (value1 > value2){
        cout << "removing value 1" << endl;
    }
    else{
        cout << "removing value 2" << endl;
    }

    // Add the contents of the first list to the third.
    list3 = list1;
    for (size_t i = 0; i < 50; i++)
    {
        list3.pop_back();
        list3.push_front(list3.pop_back());
    }

    // Print the contents in the list.
    printList(list3);

    // Checks the size of both lists and then add them to the fourth list, listed in smallest value to largest.
    size_t counter = list1.size() + list2.size();
    while (!list1.is_empty() || !list2.is_empty())
    {
        if (list1.front() < list2.front() && !list1.is_empty())
            list4.push_back(list1.pop_front());
        else
            list4.push_back(list2.pop_front());

        counter--;
    }

    // Print the contents in the list and then check to make sure the list is not sorted.
    printList(list4);
    for (unsigned i = 1; i < list4.size() - 1; i++)
    {

        if (list4.at(i) > list4.at(i + 1))
            cout << "ERROR! It is in the wrong order!";
    }

    getchar();
    return 0;
}

void printList(linked_list list){
    list.print();
}

表达式 !is_empty!is_empty() 不等价。

这一行

class linked_list {
    //.....
private:
    struct node_t {
        node_t(double value, node_t * next = 0, node_t * prev = 0);
        //.....
    }
    //.....
};

声明了 linked_list::node_t class 的构造函数,但没有说明该函数应该做什么。

要么用内联体扩展它:

class linked_list {
    //.....
private:
    struct node_t {
        node_t(double value, node_t * next = 0, node_t * prev = 0)
        {
            this->value = value;
            this->next  = next;
            this->prev  = prev;
        }
        //.....
    }
    //.....
};

或添加独立实施

linked_list::node_t::node_t(double value, node_t * next, node_t * prev)
{
    this->value = value;
    this->next  = next;
    this->prev  = prev;
}