【问题标题】:C++ run time error with protected members受保护成员的 C++ 运行时错误
【发布时间】:2009-10-10 07:59:01
【问题描述】:

我正在尝试做一个家庭作业,我们使用链接堆栈将字符串插入到指定点的字符串中,因此使用了 struct 和 typedef。无论如何,当我尝试在 InsertAfter 方法内的 StringModifier 类中访问 stringLength 时,我得到一个运行时错误,我无法弄清楚问题是什么。我应该能够访问和修改该变量,因为它是受保护的并且派生类是公开继承的。

struct StringRec
{
    char theCh;
    StringRec* nextCh;
};

typedef StringRec* StringPointer;

class String
{
    public:
        String();
        ~String();
        void SetString();
        void OutputString();
        int GetLength() const;
    protected:
        StringPointer head;
        int stringLength;
};

class StringModifier : public String
{
    public:
        StringModifier();
        ~StringModifier();
        void InsertAfter( StringModifier& subString, int insertAt );
};

void StringModifier::InsertAfter( StringModifier& subString, int insertAt )
{
// RUN TIME ERROR HERE
    stringLength += subString.stringLength;
}

在主要

StringModifier test;
StringModifier test2;

cout << "First string" << endl;
test.SetString();
test.OutputString();
cout << endl << test.GetLength();
cout << endl << "Second string" << endl;
test2.SetString();
test2.OutputString();
cout << endl << test2.GetLength();
cout << endl << "Add Second to First" << endl;
test.InsertAfter( test2, 2 );
test.OutputString();
cout << endl << test.GetLength();

//String Class

String::String()
{
    head = NULL;
    stringLength = 0;
}

String::~String()
{
// Add this later
}

void String::SetString()
{
    StringPointer p;
    char tempCh;

    int i = 0;
    cout << "Enter a string: ";
    cin.get( tempCh );
// Gets input and sets it to a stack
    while( tempCh != '\n' )
    {
        i++;
        p = new StringRec;
        p->theCh = tempCh;
        p->nextCh = head;
        head = p;
        cin.get( tempCh );
    }

    stringLength = i;
}

void String::OutputString()
{
    int i = stringLength;
    int chCounter;
    StringPointer temp;
// Outputs the string bottom to top, instead of top to bottom so it makes sense when read
    while( head != NULL && i > 0 )
    {
        temp = head;
        chCounter = 0;
        while( temp != NULL && chCounter < (i-1) )
        {
            temp = temp->nextCh;
            chCounter++;
        }
        cout << temp->theCh;
        i--;
    }
}

int String::GetLength() const
{
    return stringLength;
}

StringModifier 类有空的构造函数和析构函数。

【问题讨论】:

  • 检查 SetString 是否正常工作。对我来说似乎是内存错误。

标签: c++ string class protected


【解决方案1】:

提示:C++ 中的运行时错误与公共/受保护/私有访问完全无关。编译器在编译你的代码时,已经检查了所有的类成员访问规则是否被遵循。

运行时错误意味着您的程序中存在错误,很可能是某种内存损坏。

【讨论】:

  • 当我运行它时,当我尝试从方法中更改 stringLength 时,程序总是停止工作。如果我不尝试修改它,它运行良好。
  • 将访问权限从protected 更改为public 并重新运行您的程序。糟糕——程序仍然崩溃!怎么会?
  • 是的,但问题不在于protected 访问。您的代码中某处存在错误,如果无法查看其余代码,我们将无法猜测出哪里。
  • 我认为问题不是成员访问说明符,但我没有其他想法。哈哈。不过我不知道用哪种方法来解决它。
  • 两个建议:(1)如有疑问,请打印更多内容。 (2) 借此机会了解一下您的开发环境中的调试器可以为您做什么。
【解决方案2】:

您确定运行时错误位置吗?你是怎么检查的?我看到一个地方很可疑:

while( temp != NULL && chCounter < (i-1) )
{
        temp = temp->nextCh;
        chCounter++;
}
cout << temp->theCh; // temp can be NULL here?

temp != NULL 在循环头中始终为 true,或者在某些情况下您确实有 NULL 指针取消引用,这本身就是运行时错误。

【讨论】:

  • 当我在输出方法中使用该循环输出时,它对我来说很好。我确定错误位置,因为当我取出它时,所有其他方法都可以正常工作,但是一旦我尝试 InsertAfter 它就会崩溃。
【解决方案3】:

您可以尝试在 Valgrind(免费)或 Purify(可能不是免费)下运行您的程序,以尽早检测内存错误。错误信息也应该更加清晰。

另外,只需在调试器下运行程序,当它崩溃时,检查它的状态。是你所期望的吗?

【讨论】:

    【解决方案4】:

    您确定您的运行时错误确实发生在 InsertAfter 函数中吗?在我看来,当您修改 stringLength 时,您应该在 OutputString 中遇到访问冲突,因为您实际上还没有添加字符。将 (temp != NULL) 子句添加到您的 while 循环 几乎 可以避免这种情况 - 但看看如果由于 temp 变为 NULL 而实际离开循环会发生什么......

    回复你们的cmets:恐怕我还是有点怀疑这个运行时错误发生在哪里!如果代码确实如问题中给出的那样,并且假设您没有混乱的构建,那么在 InsertAfter 中拥有 AV 或其他东西几乎是不可能的(好吧,这在 C++ 中说起来很危险,但是嘿-您只是在更改分配在堆栈上的对象成员的值)。请注意,您不能仅仅因为如果您不调用它就会在 InsertAfter 方法中发生错误 - 实际上 OutputString 中的错误仅通过调用 InsertAfter 暴露,所以它应该 如果 InsertAfter 调用被删除,则消失。要进行检查,请使用调试器,或者在可疑语句之前和之后向 InsertAfter 添加一些日志记录。

    【讨论】:

    • 是的,我确信它发生在 InsertAfter 方法中。我可以使用 String 类中的所有其他方法。当我尝试访问 stringLength 并从 StringModifier 派生类修改它时,会导致运行时错误。
    【解决方案5】:

    感谢大家的帮助。事实证明,我一开始就在列表中添加了错误的东西。我没有把它变成一个堆栈,而是把它变成了一个队列,一切都很好!我听取了你们提供的建议,并在别处寻找问题所在。谢谢!

    void String::SetString()
    {
        StringPointer p, last;
        char tempCh;
        last = head;
        int i = 0;
        cout << "Enter a string: ";
        cin.get( tempCh );
    
        while( tempCh != '\n' )
        {
            i++;
            if( i == 1 )
            {
                p = new StringRec;
                p->theCh = tempCh;
                head = p;
                last = p;
            }
            else
            {
                p = new StringRec;
                p->theCh = tempCh;
                p->nextCh = last;
                last->nextCh = p;
                last = p;
            }
            cin.get( tempCh );
        }
    
        last->nextCh = NULL;
    
        stringLength = i;
    }
    

    【讨论】:

      猜你喜欢
      • 2016-06-12
      • 2014-06-09
      • 1970-01-01
      • 2016-01-07
      • 2023-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-03
      相关资源
      最近更新 更多