首页 > 解决方案 > 为什么嵌套类对外部类不可见

问题描述

我对嵌套类的问题感到困惑

#ifndef MINIGRAPH_H_
#define MINIGRAPH_H_
#include<vector>
#include<list>
#include<iostream>
template <typename VEX,typename EDGE>
class MiniGraph
{
public:
    class _Node
    {
    public:
        VEX _Vex;
        EDGE _Edge;
         _Node* next;
    };
    MiniGraph() {};
    MiniGraph(int vex_num);
    void add(VEX from, VEX to, EDGE Edge);
    //void display();
private:
    std::vector<void*> _VecNode;
    _Node* NewNode(VEX vex) { _Node* ptr = new _Node;ptr->_Vex = vex;return ptr; }
    _Node* NewNode(VEX vex, EDGE edge) { _Node* ptr = new _Node;ptr->_Vex = vex;ptr->_Edge = edge;return ptr; }

};
template <typename VEX, typename EDGE>
MiniGraph<VEX, EDGE>::MiniGraph(int vex_num)
{
    int i = 0;
    for (i = 0;i < vex_num;i++)
    {
        struct Node *ptr_tmp = new _Node;
        ptr_tmp->next = NULL;
        _VecNode.push_back(ptr_tmp);
    }
}
template <typename VEX, typename EDGE>
void MiniGraph<VEX, EDGE>::add(VEX from, VEX to, EDGE edge)
{
    int i;
     _Node* ptr_node = NULL;
    for (i = 1;i < _VecNode.size();i++)
    {
        ptr_node = (_Node*)_VecNode[i];
        if (ptr_node->_Vex == from)
            break;
    }
    if (i == _VecNode.size())
    {
        ptr_node = NewNode(from);
        _VecNode.push_back(ptr_node);
    }
    ptr_node = NewNode(from, edge);
    **ptr_node->next = (_Node*)_VecNode[i]->next;//insert node from head**
    _VecNode[i]->next = ptr_node;
}

编译时

#include "MiniGraph.h"
void main()
{
    MiniGraph<int, double> hh;
    hh.add(1, 2, 0.1);
    hh.add(1, 3, 0.2);
    hh.add(2, 3, 0.3);
}

ptr_node->next = (_Node*)_VecNode[i]->next;//insert node from head 说 -> 左下角必须指向类/结构/联合/通用类型时触发的错误;但是_Node被声明了。我试图用结构替换类,但它触发了同样的错误。似乎声明不可见。我应该如何解决这个问题?

标签: c++nesteddeclaration

解决方案


正如上面评论中提到的@WhozCraig,您有一个 的向量void*,而不是 的向量Node*。因此没有被调用的成员next。您可以将 type_cast 转换void*为 aNode*来“修复”问题,但您会大吃一惊。

问题从你的main功能开始。

int main()
{
    MiniGraph<int, double> hh;

此代码将调用该类的默认构造函数MiniGraph。这意味着 noNodes将被创建,并且您的向量 ofNode*将为空(即std::vector<Node*>::size = 0.

然后调用add函数:

hh.add(1, 2, 0.1);

add函数内部会发生以下情况:

void add(VEX from_, VEX to_, EDGE edge_)
{
    std::size_t i = 0;

    for (i=1; i<node_ptrs.size(); i++)
    {
        if (node_ptrs[i]->vex == from_)
            break;
    }

在第一次调用之后add(),向量size = 0,但是i = 1。那是因为您i=1在 for 循环中进行了初始化。

然后检查是否i == vector::size.

    Node *tmp = nullptr;
    if (i == node_ptrs.size())
    {
        tmp = NewNode(from_);
        node_ptrs.push_back(tmp);
    }

上面的 if 语句永远不会被执行,因为i = 1vector::size = 0.

最后,您执行以下操作:

    tmp = NewNode(from_, edge_);
    tmp->next = node_ptrs[i]->next; // this fails because your vector size is 0!
    node_ptrs[i]->next = tmp;

第一行有效。tmp是一个Node*指向新创建的Node. 好的。然后程序因分段错误而失败,因为tmp->next它试图浅拷贝i向量元素中的指针。现在请记住,i = 1向量仍然是空的,即vector::size = 0。没有node_ptrs[1]可复制的元素。这就是它崩溃的原因。

上述代码示例:https ://rextester.com/DTODK86272

在您的原始代码中还有更多问题需要考虑......例如:

  • 如果只有一个指针指向某个Node,则使用unique_ptr. 您仍然可以从 a 读取其他指针unique_ptr,但他们将无法做任何其他事情。
  • 编写初始化指针的构造函数,并在and成员nullptr上调用零初始化。vexedge
  • 避免int用作数组索引。如果有人决定使用负数作为函数参数怎么办?
  • 在您的实现中,您必须在开始执行任何其他操作之前检查向量是否为空。如果向量为空,会发生什么?

推荐阅读