Невозможно получить доступ к члену объекта через указатель - PullRequest
0 голосов
/ 10 октября 2018

Эта проблема кажется тривиальной, но я не могу обойти ее.

Я пытаюсь добавить узел, передав корневой элемент функции insert.Функция сначала проверяет, является ли текущий корень пустым, если это так, она просто создает новый узел и устанавливает его в качестве корня.Моей первой попыткой было что-то вроде этого

#include <iostream>

using namespace std;

class Node {
    public:
        int data;
        Node(int x) {
            data = x;
        }
};

void insert(Node *node, int x) {
    cout << &node << "\n";
    if(node == NULL) {
        node = new Node(x);
    }
}



int main () {
    Node *aNode;
    aNode = NULL;
    insert(aNode, 8);
    cout << aNode << "\n";
    return 0;
}

Это, конечно, не сработало, так как я передавал указатели по значению, из-за чего aNode был все еще NULL, и с некоторым поиском я узналМне нужно передать указатели по ссылке, моя вторая попытка была примерно такой:

#include <iostream>

using namespace std;

class Node {
    public:
        int data;
        Node(int x) {
            data = x;
        }
};

void insert(Node **node, int x) {
    if(*node == NULL) {
        *node = new Node(x);
        cout << *node->data << "\n"; //gives error but program runs fine without it
    }
}



int main () {
    Node *aNode;
    aNode = NULL;
    insert(&aNode, 8);
    cout << aNode->data << "\n";
    return 0;
}

Теперь это работало без функции вставки cout in, поскольку cout in main напечатало 8, чточто я хотел, но компилятор выдал ошибку request for member 'data' in '* node', which is of pointer type 'Node*' (maybe you meant to use '->' ?) при cout вставки.Я изменил вставку следующим образом, чтобы выполнить некоторые тесты, и результаты приводили в замешательство

void insert(Node **node, int x) {
    if(*node == NULL) {
        Node *bNode = new Node(x);
        cout << bNode << "\n"; // prints address of bNode
        cout << *node << "\n"; // prints NULL which is correct
        *node = bNode;
        cout << *node << "\n"; // prints the same address as of bNode
        cout << bNode->data << "\n"; // prints 8
        cout << *node->data << "\n"; // gives error WTF!!!
    }
}

Может кто-нибудь объяснить, пожалуйста?

1 Ответ

0 голосов
/ 11 октября 2018

@ Комментарий РемиЛебо был замечен и указал на точную проблему.Итак, вот решение.

Фон проблемы

Итак, у меня был указатель на объект типа Node aNode и функция insert(Node *node, int x).Я хотел, чтобы функция insert проверила, не указывает ли данный указатель на узел что-либо, затем создала новый узел и установила ссылку в предоставленном узле.Ожидалось, что после установки ссылки aNode также будет указывать на вновь созданный узел.Однако это было ложное ожидание, потому что я передавал указатель по значению вместо ссылки, что означало, что node в функции insert отличался от aNode

Buggy Solution

Таким образом, решением было передать ссылку aNode в функцию insert.Поэтому я изменил свой вызов функции на insert, на это

insert(&aNode, 8);

И изменил определение функции insert на это

void insert(Node **node, int x)

Это решило проблему, так как **node теперь был разыменован по адресу aNode, и я смог получить его значение, просто разыменовав node на *node.Проблема возникла, когда я попытался получить доступ к членам Node по *node->data.Причина в том, что * и -> на самом деле являются операторами, а -> имеет более высокий приоритет, чем *.Таким образом, при оценке *node->data он фактически выполнялся таким образом *(node->data), что означает, что компилятор фактически пытался разыменовать node->data вместо node.Быстрое решение состояло в том, чтобы просто получить доступ к таким данным (* узел) -> данные.

Правильное решение

Хотя с помощью скобок я смог добиться желаемого поведения, но синтаксис был уродливым.Правильное решение, как @ pm100, указывало на использование ссылки в определении функции вместо разыменования ее дважды, что означает объявление функции следующим образом

void insert(Node *&node, int x)

вместо этого

void insert(Node **node, int x)

Это позволило получить доступчлены узла просто как node->data вместо (*node)->data

Если вы новичок в указателях, как я, то посмотрите https://www.youtube.com/watch?v=Rxvv9krECNw

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...