You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++ List类setEntry函数异常处理问题及实现疑问

问题分析与解决方案

核心错误点

  • 异常检查顺序颠倒:你的setEntry函数先执行赋值操作list[pos] = item,再判断pos是否合法。这会导致两个问题:一是触发非法内存访问(比如空列表时pos=2,数组下标越界),二是即使抛出异常,之前的非法操作已经引发未定义行为。
  • 数组下标偏移错误:类的接口规定pos从1开始(范围1~getLength()),但C++数组下标从0开始,直接使用list[pos]会修改错误的位置,甚至触发越界。
  • 未捕获的异常:main函数开头调用songs.setEntry(2, "Bohemian Rhaspody")时,列表是空的(getLength()返回0),pos=2超出合法范围触发异常,但这个调用没有被try-catch块包裹,导致程序直接终止。

修正后的setEntry函数

必须遵循先检查合法性,再执行操作的原则,同时修正数组下标:

#include <stdexcept> // 必须包含此头文件以使用std::invalid_argument

template<class ItemType>
void List<ItemType>::setEntry(int pos, const ItemType& item)
{
    // 第一步:检查位置合法性,不合法直接抛出异常
    if (pos < 1 || pos > getLength())
    {
        throw std::invalid_argument("ERROR: setEntry() using invalid position");
    }
    // 第二步:合法则修改对应位置(数组下标=pos-1)
    list[pos - 1] = item;
}

修正main函数以处理异常

如果要测试异常功能,必须将setEntry的调用放到try-catch块中,同时避免在空列表时调用setEntry:

#include <iostream>
#include <string>
#include <stdexcept>
using namespace std;

// 实现getTrack函数示例
int getTrack() {
    int num;
    cout << "Enter track number: ";
    cin >> num;
    return num;
}

// 插入你的List类定义...

int main()
{
    List<string> songs;
    char goAgain = 'y';
    int trackNumber;
    string trackName;
    
    // 先插入元素,让列表有合法的位置范围
    songs.insert(1, "Bohemian Rhaspody");
    songs.insert(2, "The Highway Song");
    songs.insert(3, "In the Loop");
    songs.insert(4, "Lovesong");
    songs.insert(5, "Blow The Whistle");
    songs.remove(1);

    // 测试setEntry的异常处理
    try {
        songs.setEntry(2, "Updated Highway Song"); // 合法位置,正常执行
        cout << "成功修改第2首歌\n";
        
        songs.setEntry(5, "Invalid Track"); // 非法位置,触发异常
    } catch (const std::invalid_argument& e) {
        cout << "捕获到异常:" << e.what() << endl;
    }
      
    cout << "Welcome!  There are " << songs.getLength() << " tracks.\n";
    while (goAgain != 'n')
    {
        trackNumber = getTrack();
        try
        {
            trackName = songs.getEntry(trackNumber);
        }
        catch (const std::invalid_argument& arg)
        {
            cout << arg.what() << endl;
            trackName = "No Track";
        }
        cout << "Your track name is " << trackName << endl;
        cout << "Go again? (y/n) ";
        cin >> goAgain;
    }
    
    cout << "you're ready to rock!\n";
    return 0;
}

关键注意事项

  • 必须包含<stdexcept>头文件,否则std::invalid_argument无法被编译器识别。
  • 捕获异常时建议使用const引用(const std::invalid_argument& e),避免不必要的异常对象拷贝。
  • 永远先验证输入合法性,再执行核心操作,防止非法内存访问引发的未定义行为。

内容的提问来源于stack exchange,提问作者evanparial

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 10:42:22