Возвращение указателя или ссылки на мой текущий объект из функции insert_node в программе со связанным списком - PullRequest
0 голосов
/ 14 апреля 2020

Я новичок в C ++. и я писал link list, в котором я могу вызвать мою функцию для вставки узлов следующим образом:

(при условии, что a и b и c - это данные, которые я хочу вставить в link list.

list.insert(a)->insert(b)->insert(c);

и я сделал это так:

#include <iostream>
using namespace std;

class Node {
public:
    char letter;                     
    Node* next;     
};

class link_list {

private:
    Node* head;       
public:

    link_list() {             
        head = NULL;
    }
    link_list* insertNewNode(char item);
};


link_list* link_list::insertNewNode(char item) {
    Node* temp;
    temp = new Node;
    temp->letter = item;
    temp->next = head;
    head = temp;
    return this;
}

int main() {

    link_list list;
    list.insertNewNode('a')->insertNewNode('b')->insertNewNode('c');
    return 0;
}

в моей функции insertNewNode я возвращаю указатель на мой текущий объект. И он работает нормально, однако Я не уверен, что мой метод верен?

Но я должен также объяснить, что произойдет, если вместо возврата указателя или ссылки на мой текущий объект я верну свой текущий объект.

поэтому я попробовал это:

class Node {
public:
    char letter;                     
    Node* next;     
};


class link_list {

private:
    Node* head;       
public:

    link_list() {             
        head = NULL;
    }
    link_list insertNewNode(char item);
};


link_list link_list::insertNewNode(char item) {
    Node* temp;
    temp = new Node;
    temp->letter = item;
    temp->next = head;
    head = temp;
    return *this;
}
int main() {

    link_list list;
    list.insertNewNode('a')->insertNewNode('b')->insertNewNode('c');
    return 0;
}

, а затем я получил ошибку, в которой говорилось, что list должен быть указателем, поэтому я изменил свой основной на:

int main() {

    link_list *list;
    list = new link_list;
    list->insertNewNode('a')->insertNewNode('b')->insertNewNode('c');
    return 0;
}

, но я все еще получая эту ошибку, которая сказала здесь list->insertNewNode('a')->insertNewNode('b')->insertNewNode('c'); выражение должно иметь тип указателя , и эти две ошибки:

1.type 'link_list' не перегружен член 'operator ->'

2 .'-> link_list :: insertNewNode ': левый операнд имеет тип' class ', используйте '.'

так вот мои вопросы с целью вызова функции вставки, подобной этой list.insert(p1)->insert(p2)->insert(p3);, мой путь в первой программе правильный? а также возможно ли вернуть мой текущий объект для этой цели? и что будет, если я верну текущий объект?

PS: извините за длинный вопрос, а также спасибо заранее за вашу помощь.

Ответы [ 2 ]

5 голосов
/ 14 апреля 2020
  1. Что ж, в вашем текущем методе нет ничего криминального, возвращающего указатель. Не то, что делается очень часто, все еще довольно компилируемо.

  2. Больше идиоматических c будет возвращать текущий объект по ссылке:

link_list &insert(char elem) {
    return *this;
}

Ваша первоначальная проблема заключалась в том, что вы изменили тип возврата метода, но сохранили -> в main(). Если вы измените тип возврата insert на ссылку из указателя, то цепочечные вызовы должны выполняться через ., поскольку вы работаете с объектами и ссылками на них, а не с указателями.

Возвращение копии текущего объекта из установщика - это не то, что нужно делать, особенно если вы управляете частными ресурсами самостоятельно и еще не определили правильный конструктор копирования. Скорее верните ссылку.

1 голос
/ 14 апреля 2020

Ваш метод выглядит хорошо. Вы делаете

link_list* insertNewNode(char) {
  // ...
  return this;
}

, так что вы можете связать вставки следующим образом:

list.insertNewNode('a')->insertNewNode('b')->insertNewNode('c'); 

Вы также можете вернуть ссылку на link_list, например,

link_list& insertNewNode(char) {
  // ...
  return *this;
}

и теперь цепочка вставок выглядит следующим образом

list.insertNewNode('a').insertNewNode('b').insertNewNode('c'); 

Обратите внимание, что вы не должны делать что-то вроде

link_list insertNewNode(char) {
  // ...
  return *this;
}

, потому что это скомпилируется, но вы бы возвращали копия связанного списка, и цепочка просто не будет работать.

Если ваши узлы будут добавлены в хвост, конструктор копирования по умолчанию заставит его выглядеть как если цепочка работает, потому что оригинал link_list будет видеть все Nodes, добавленные к копии.

В вашей реализации вы добавляете Nodes в заголовок, поэтому оригинальный link_list не видит Nodes добавлено к копии, поэтому цепочка не работает. Это хорошо, потому что копии будут терять утраченную память, даже если вы напишите правильный деструктор.

...