在c ++中从char *获得奇怪的返回值

时间:2012-09-07 22:08:47

标签: c++ char

我是c ++编程的新手,我从一个我设置的char *变量中得到了一个奇怪的值,这取决于我如何使用它。我显然做了一些非常愚蠢的事情,但我看不出问题。接下来的几段描述了设置(很糟糕),但是看看输出和代码可能更容易。

基本上,我有几个类 - Menu和MenuItem。 MenuItem类的名称类型为char *。根据我使用菜单项的方式,当我在MenuItems上执行getName()时,我会得到奇怪的结果。

我有一个具有状态(TestState)的Machine类。此TestState创建一个包含MenuItems的Menu。当我在我的主函数中创建一个TestState并打印出菜单时,我得到了我的期望。当我创建一个包含TestState并要求它打印菜单的机器时,它会在菜单中打印一些奇怪的根项目名称。

输出 - 最后一行我期待 menuItem1 ,但我得到HâΔHã=ò

Output direct from TestState Object

Displaying menu state 
menuItem1
root not null 
menuItem1


Output from TestState within Machine

Displaying menu state 
menuItem1
root not null 
Hâ∆Hã=ò

这是我的代码 - Main.cpp的

#include "Menu.h"
#include "Machine.h"
#include <iostream>

using namespace std;

Machine m;
TestState t;

int main(void) {
    cout << "Output direct from TestState Object" << endl << endl;
    t = TestState();
    t.print();


    cout << endl << endl << "Output from TestState within Machine" << endl << endl;
    m = Machine();
    m.printCurrentState();
}

Menu.h

#ifndef Menu_h
#define Menu_h

#include <stdlib.h>

class MenuItem {
public:
    MenuItem();
    MenuItem(const char* itemName);
    const char* getName() const ;

protected:
    MenuItem *next;
    const char* name;
};

class Menu {
public:
    Menu(MenuItem *rootItem);
    Menu();
    void setRoot(MenuItem *r);
    MenuItem* getRoot() ;
protected:
    MenuItem *root;
};

#endif

Machine.h

#ifndef MACHINE_H_
#define MACHINE_H_

#include "Menu.h"

class TestState;
class Machine;

class TestState {
public:
    TestState();
    virtual ~TestState();
    void print();
protected:
    Machine* machine;
    MenuItem menuItem1;
    Menu menuMain;
};

class Machine {
public:
    Machine();
    void printCurrentState();
protected:
    TestState testState;
};

#endif /* MACHINE_H_ */

Machine.cpp

#include "Machine.h"
#include <iostream>
using namespace std;

TestState::TestState() {
    menuItem1 = MenuItem("menuItem1");
    menuMain = Menu(&menuItem1);
}

void TestState::print(){
    cout << "Displaying menu state " << endl;
    cout << menuItem1.getName() << endl;

    if (menuMain.getRoot() == NULL) {
        cout << "root is null" << endl;
    } else {
        cout << "root not null " << endl;
        cout << menuMain.getRoot()->getName() << endl;
    }
}

TestState::~TestState() {
    // TODO Auto-generated destructor stub
}

Machine::Machine() {
    testState = TestState();
}

void Machine::printCurrentState() {
    testState.print();
}

任何帮助将不胜感激。我有点迷茫。 谢谢 戴夫

4 个答案:

答案 0 :(得分:4)

我怀疑发生了什么Menu.root指向某处的临时对象。您会注意到您在主要功能中复制了您的机器:

// in main():
m = Machine(); // makes a machine, then copies it

该计算机的TestState有一个MainMenu,其指针指向MenuItem

// in MenuItem class definition:
MenuItem *root;

该指针初始化为原始机器成员的地址。问题是,该对象只存在很短的时间:它在复制完成时被销毁,留下一个悬空指针。

换句话说,您需要确保在复制包含指针的对象时,更新这些指针以反映重复对象的地址而不是旧对象的地址。

您需要添加如下所示的复制构造函数:

Machine::Machine(const Machine& other)
{
    teststate = other.teststate;
    teststate.machine = this; // you will need to expose TestState.machine to Machine
}

TestState::TestState(const TestState& other)
{
    machine = other.machine; // Machine copy constructor modifies this for us

    menuItem1 = other.menuItem1; // these 3 we have to do
    menuItem2 = other.menuItem2;
    menuMain = other.menuMain;

    menuMain.setRoot(&menuItem1); // update pointers to be to persistent copies
    menuItem1.setNext(&menuItem2);
    menuItem2.setNext(NULL);
}

您可能会注意到您的系统相当脆弱。我建议依靠较少的物体之间的指针,因为龙在那条路上。

答案 1 :(得分:1)

TestState::TestState() {
    menuItem1 = MenuItem("menuItem1");
    menuItem2 = MenuItem("menuItem2");
    menuMain = Menu(&menuItem1);
    menuMain.add(&menuItem2);
}

Machine::Machine() {
    testState = TestState();
}

Machine构造函数构造一个临时TestState并将其数据成员复制到Machine::testState。完成Machine构造函数后,临时TestState消失,但Machine::testState.menuMain.root仍然指向临时成员。

如何解决:

了解初始化变量的各种方法的含义,以及如何在构造函数中使用初始化列表。

答案 2 :(得分:1)

而不是写Thing name = Thing(ctorParams);使名称成为指针并使用new Thing(ctorParams);。看起来你以为你在使用指针,但它没有使用new关键字,所以你继续使用它们会导致你的错误。

答案 3 :(得分:0)

Machine没有复制构造函数,因此Machine(特别是TestState内)中的各种指针和引用都指向垃圾。