Невозможно инициализировать параметр типа TreeNode с помощью выражения типа std :: shared_ptr_access. - PullRequest
0 голосов
/ 29 апреля 2020

Я пытаюсь создать связанный список, в котором хранится указатель на двоичное дерево. Класс двоичного дерева - это подкласс, полученный из обобщенного c TreeNode класса, который я создал.

В классе TreeNode реализован метод AddNode (просто как фиктивный, но он должен вызываться), но когда я пытаюсь вызвать этот метод из подкласса TreeNode, я получаю следующую ошибку:

Cannot initialize object parameter of type 'TreeNode' with an expression of type: 'std::__shared_ptr_access<ArtistPlaysNode>,__gnu_cxx::_S_atomic, false, false>::element_type'(aka 'ArtistPlaysNode')

Вот соответствующая часть TreeNode класса:

// TreeNode.h
class TreeNode {
protected:
    int key;
    int height;
    shared_ptr<TreeNode> father;
    shared_ptr<TreeNode> left;
    shared_ptr<TreeNode> right;
public:
    explicit TreeNode(int key);

    TreeNode(int key, shared_ptr<TreeNode> father, shared_ptr<TreeNode> left, shared_ptr<TreeNode> right);

    virtual StatusType AddNode(shared_ptr<TreeNode> node);
};

// TreeNode.cpp
StatusType TreeNode::AddNode(shared_ptr<TreeNode> node) {
    return INVALID_INPUT;
}

Вот ArtistPlaysNode:

// ArtistPlaysNode.h
class ArtistPlaysNode : public TreeNode {
private:
    int artistId;
    shared_ptr<SongPlaysNode> SongPlaysTree;
    shared_ptr<MostPlayedListNode> ptrToListNode;
public:
    ArtistPlaysNode(int artistId);
    ArtistPlaysNode(int artistId, shared_ptr<SongPlaysNode> ptrToSongPlaysTree, shared_ptr<MostPlayedListNode> ptrToListNode);
    int GetArtistId();
};

Вот связанный список, называемый MostPlayedListNode:

// MostPlayedListNode.h
class MostPlayedListNode {
private:
    int numberOfPlays;
    shared_ptr<ArtistPlaysNode> artistPlaysTree;
    shared_ptr<ArtistPlaysNode> ptrToLowestArtistId;
    shared_ptr<SongPlaysNode> ptrToLowestSongId;
    shared_ptr<MostPlayedListNode> previous;
    shared_ptr<MostPlayedListNode> next;

public:
    // Create the first node in the list (0 plays)
    MostPlayedListNode(int numOfPlays);

    // Create a new node with a new highest number of plays
    MostPlayedListNode(int numOfPlays, shared_ptr<MostPlayedListNode> previous);

    // Create a new node with a number of plays between to values (1<2<3)
    MostPlayedListNode(int numOfPlays, shared_ptr<MostPlayedListNode> previous, shared_ptr<MostPlayedListNode> next);

    bool AddArtist(shared_ptr<ArtistPlaysNode> artistNode);
};

А вот функция, в которой возникает ошибка:

// MostPlayedListNode.cpp
bool MostPlayedListNode::AddArtist(shared_ptr<ArtistPlaysNode> artistNode) {
    if (ptrToLowestArtistId) {
        // There are already artists stored in this linked list
        this->artistPlaysTree->AddNode(artistNode); // -->>> this line throws the error.
        return true
    } else {
        this->artistPlaysTree = artistNode;
        return true;
    }
    return false;
}

Я попытался переопределить метод AddNode внутри ArtistPlaysNode, но это не сработало и заставило компилятор жаловаться на невозможность приведения одного указателя к другому.

Попытка найти ответ в Интернете не вызвала значимых результатов

1 Ответ

0 голосов
/ 30 апреля 2020

Хорошо, короче говоря, ошибка была вызвана отсутствием Форвардных объявлений .

Обратите внимание, что класс ArtistPlaysNode имеет shared_ptr типа MostPlayedListNode и типа SongPlaysNode как его участники. И в то же время класс MostPlayedList имеет shared_ptr типа ArtistPlaysNode и типа SongPlaysNode в качестве членов.

Кроме того, ArtistPlaysNode и SongPlaysNode являются производными от TreeNode class.

Это создает сценарий, в котором эти классы имеют члены другого типа, почти циклически c.

Обычно это приводит к ошибкам типа:

expected class name before '{' token. как видно из этого вопроса

Или это может вызвать ошибку типа:

'NAME' was not declared in this scope как видно из введите описание ссылки здесь

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

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

В случае мой код, исправление было добавление предварительных объявлений в классе F файлов MostPlayedListNode, SongPlaysNode и ArtistPlaysNode.

, например, верхняя часть обновленного файла MostPlayedListNode.h:

using std::shared_ptr;
using std::make_shared;

class ArtistPlaysNode; // this is a forward declaration
class SongPlaysNode; // this is a forward declaration

class MostPlayedListNode {
private:
    int numberOfPlays;
    shared_ptr<ArtistPlaysNode> artistPlaysTree;
    shared_ptr<ArtistPlaysNode> ptrToLowestArtistId;
    shared_ptr<SongPlaysNode> ptrToLowestSongId;
    shared_ptr<MostPlayedListNode> previous;
    shared_ptr<MostPlayedListNode> next;

public:

и обновленный файл ArtistPlayesNode.h :

using std::shared_ptr;
using std::make_shared;

class SongPlaysNode; // this is a forward declaration
class MostPlayedListNode; // this is a forward declaration

class ArtistPlaysNode : public TreeNode {
private:
    int artistId;
    shared_ptr<SongPlaysNode> SongPlaysTree;
    shared_ptr<MostPlayedListNode> ptrToListNode;
public:

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

...