【问题标题】:Cannot initialize a parameter of type 'TreeNode' with an expression of type 'std::shared_ptr_access''无法使用“std::shared_ptr_access”类型的表达式初始化“TreeNode”类型的参数
【发布时间】:2020-04-29 20:24:06
【问题描述】:

我正在尝试创建一个存储指向二叉树的指针的链表, 二叉树类是从我创建的通用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;
}

我尝试在 ArtistPlaysNode 中覆盖 AddNode 方法,但这不起作用,并且编译器抱怨无法从一个指针转换到另一个指针。

尝试在线搜索答案未显示任何相关结果

【问题讨论】:

  • C++ 不是 Java。这两个共享指针的类型不同。
  • @PaulMcKenzie 这不是问题。 std::shared_ptrs 能够向上转换:ArtistPlaysNode 继承自 TreeNode。如果不是这样,std::shared_ptrs 在利用动态多态性的模式中就没有多大用处。
  • 我建议尝试一个最小的可重现示例。减少这个直到错误消失,或者你有一些足够简单的东西,你可以发布除了这个错误之外编译的代码。
  • @AzamBham -- 也许我超前了,但如果发布的代码不是实际编译的代码,那肯定是个问题。以发布的内容创建一个更小的示例,the error cannot be duplicated
  • @PaulMcKenzie 同意,我似乎也无法复制错误

标签: c++ class pointers data-structures smart-pointers


【解决方案1】:

好吧,简而言之,错误是由于缺少Forward Declarations引起的。

注意ArtistPlaysNode 类有一个MostPlayedListNode 类型和SongPlaysNode 类型的shared_ptr 作为它的成员。 同时,MostPlayedList 类的成员为“ArtistPlaysNode”类型和SongPlaysNode 类型的 shared_ptr。

此外,ArtistPlaysNodeSongPlaysNode 都派生自 TreeNode 类。

这创建了一个场景,其中这些类以几乎循环的方式具有其他类型的成员。

这通常会导致以下类型的错误:

expected class name before '{' token.this question 所示

否则可能会导致类型错误:

'NAME' was not declared in this scopeenter link description here 所示

为了解决这个问题,我们需要要么确保类、函数或头文件所依赖的所有内容在使用之前都已声明。

或者我们需要为编译器提供前向声明,这将允许编译器识别该类,而无需提供其完整定义。

就我的代码而言,修复是在MostPlayedListNodeSongPlaysNodeArtistPlaysNode 的类文件中添加前向声明。

例如,更新后的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,但情况可能并非总是如此。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多