为什么嵌套 class 对外部 class 不可见
why nested class not visible to outer class
我被嵌套的问题弄糊涂了class
#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
中触发错误
说 ->next left 必须指向 class/struct/union/generic 类型;
但是声明了_Node。我试图用结构替换class,但它触发了同样的错误。
好像声明不是visible.how我应该解决这个问题吗?
正如@WhozCraig 在上面的评论中提到的,你有一个 void*
的向量,而不是 Node*
的向量。因此没有名为 next
的成员。您可以 type_cast void*
到 Node*
到 "fix" 的问题,但您会大吃一惊。
问题从您的 main
函数开始。
int main()
{
MiniGraph<int, double> hh;
此代码将调用 MiniGraph
class 的默认构造函数。这意味着不会创建 Nodes
并且 Node*
的向量将为空(即 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
。那是因为你在 for 循环中初始化了 i=1
。
然后你检查是否i == vector::size
.
Node *tmp = nullptr;
if (i == node_ptrs.size())
{
tmp = NewNode(from_);
node_ptrs.push_back(tmp);
}
上面的 if 语句永远不会被执行,因为 i = 1
和 vector::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
。您仍然可以从 unique_ptr
读取其他指针,但它们将无法执行任何其他操作。
- 编写将指针初始化为
nullptr
的构造函数,并对 vex
和 edge
成员调用零初始化。
- 避免使用
int
作为数组索引。如果有人决定使用负数作为函数参数怎么办?
- 在您的实现中,您必须在开始执行任何其他操作之前检查向量是否为空。如果向量为空会怎样?
我被嵌套的问题弄糊涂了class
#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
中触发错误
说 ->next left 必须指向 class/struct/union/generic 类型;
但是声明了_Node。我试图用结构替换class,但它触发了同样的错误。
好像声明不是visible.how我应该解决这个问题吗?
正如@WhozCraig 在上面的评论中提到的,你有一个 void*
的向量,而不是 Node*
的向量。因此没有名为 next
的成员。您可以 type_cast void*
到 Node*
到 "fix" 的问题,但您会大吃一惊。
问题从您的 main
函数开始。
int main()
{
MiniGraph<int, double> hh;
此代码将调用 MiniGraph
class 的默认构造函数。这意味着不会创建 Nodes
并且 Node*
的向量将为空(即 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
。那是因为你在 for 循环中初始化了 i=1
。
然后你检查是否i == vector::size
.
Node *tmp = nullptr;
if (i == node_ptrs.size())
{
tmp = NewNode(from_);
node_ptrs.push_back(tmp);
}
上面的 if 语句永远不会被执行,因为 i = 1
和 vector::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
。您仍然可以从unique_ptr
读取其他指针,但它们将无法执行任何其他操作。 - 编写将指针初始化为
nullptr
的构造函数,并对vex
和edge
成员调用零初始化。 - 避免使用
int
作为数组索引。如果有人决定使用负数作为函数参数怎么办? - 在您的实现中,您必须在开始执行任何其他操作之前检查向量是否为空。如果向量为空会怎样?