1

我是一位经验丰富的 C# 程序员,并试图通过创建 Stack 对象的 C++ 应用程序来帮助朋友。自从我看到 C++ 以来,已经有 13 年多了,我正在努力回忆正确的方法来做这件事。我花了一点时间才再次了解 Header/CPP 的区别,所以那里甚至可能存在问题。这是我的问题:

//Stack.h

#ifndef __STACK_INCLUDED__
#define __STACK_INCLUDED__
#include "Node.h"

class Stack
{
    private:
    /// Going to be the pointer to our top node
    Node* m_topNode;

    /// Running count of elements
    int m_count;
    public:
    ///Constructor
    Stack();

    ///Allows us to retrieve the top value from the stack
    /// and remove it from the stack
    int Pop();
    .
    .
    .
};
#endif

下面是与标头匹配的 CPP。我在这里只是为了调试。我也完全限定了所有内容,因为我不确定这是否会导致指针问题和引用丢失。

//Stack.cpp
#include "stdafx.h"
#include "Stack.h"
#include <iostream>
Stack::Stack(){
    m_count = 0;
    m_topNode = NULL;
} 

void Stack::Push(int Value){

    std::cout << "\nPushing Value: ";
    std::cout << Value;
    std::cout << "\n";
    if ( Stack::m_topNode )
    {
        std::cout << "TopNode Value: ";
        std::cout << Stack::m_topNode->data;
        std::cout << "\n";
    }
    std::cout << "\n";

    Node newNode(Value, NULL, Stack::m_topNode);
    Stack::m_topNode = &newNode;
    Stack::m_count++;
}

节点类是一个非常简单的实体。只需要存储一个值和两边的指针。我知道我不需要在两个方向上跟踪堆栈,但我想让这个东西很容易变成一个队列或类似的结构。

//Node.h

#ifndef __NODE_INCLUDED__
#define __NODE_INCLUDED__
class Node
{
    private:

    public:
    ///Constructor allows us to specify all values. 
    /// In a stack I expect NextNode to be NULL
    Node(int Value,Node* NextNode, Node* PreviousNode);

    ///Pointer to the next node
    Node* Next;

    ///Pointer to the previous node
    Node* Prev;

    ///Value to be stored
    int data;
}; 
#endif

非常简单的实现: //Node.cpp #include "stdafx.h" #include "Node.h"

Node::Node(int Value, Node* NextNode, Node* PreviousNode){
    data = Value;
    Next = NextNode;
    Prev = PreviousNode;
}

我的主要任务是现在通过 Push 将 2 个值发送到堆栈并查看这些值正在打印什么:

#include "stdafx.h"
#include "Node.h"
#include "Stack.h"
using namespace std;

int main(){
    Stack s = Stack();

    for ( int i = 0; i < 2; i++ ){
        s.Push(i * 10);
    }

    int blah;
    cin >> blah; //Stall screen
    return 0;
}

这是输出:

 Pushing Value: 0

 <blank line>
 Pushing Value: 10
 TopNode Value: -858993460

当我在调试器中点击 Node newNode(Value, NULL, Stack::m_topNode) 时,我可以看到它跟踪当前节点中的正确值,但 m_topNode 引用了一个非常奇怪的值。我希望很明显我在做一些愚蠢的事情,因为我不记得几年前我做这件事时这很棘手。感谢对我不正确的举止的任何帮助/见解。

4

3 回答 3

5
Node newNode(Value, NULL, Stack::m_topNode);
Stack::m_topNode = &newNode;
Stack::m_count++;

这是你的问题。您在当前堆栈上分配新节点,然后将指针放入节点链表中。一旦您的堆栈帧返回,此指针将无效,并且所有的地狱中断都会丢失。;)

您需要使用 new 分配节点。

于 2013-09-25T18:30:28.217 回答
2

正如 Norwæ 所说,您需要为 newNode 分配“new”,因为如果您不这样做,您的 newNode 是静态的,并且在 Push 函数结束时将超出范围。

您还需要在没有“Stack::”的情况下调用您的私有成员,因为这在 C++ 中仅用于访问静态类成员和函数。仅将“Stack::m_topNode”替换为“m_topNode”,将 Stack::m_count 替换为 m_count。

这是一个有效的推送功能:

void Stack::Push(int Value){

std::cout << "\nPushing Value: ";
std::cout << Value;
std::cout << "\n";
if ( m_topNode )
{
    std::cout << "TopNode Value: ";
    std::cout << m_topNode->data;
    std::cout << "\n";
}
std::cout << "\n";

Node * newNode = new Node(Value, NULL, m_topNode);
m_topNode = newNode;
m_count++;

}
于 2013-09-25T19:05:31.223 回答
0

这一行:

std::cout << Stack::m_topNode->data;

发生在之前

Node newNode(Value, NULL, Stack::m_topNode);
Stack::m_topNode = &newNode;
Stack::m_count++;

所以你试图打印一个未初始化的值。颠倒这些,看看会发生什么。

于 2013-09-25T18:33:13.290 回答