尝试/捕获的奇怪行为

Odd behavior of try/catch

本文关键字:尝试      更新时间:2023-10-16

我的问题是:为什么下面的代码:

class A
{
public:
    A()
    {
        test[0] = "three";
        test[5] = "five";
        test2[3] = 5.55;
    }
    void foo(int j)
    {
        for(int i = j+1; i <= 7; ++i)
        {
            try
            {
                std::cout<<test.at(i)<<"n";
            }
            catch(const std::out_of_range&)
            {
                try
                {
                    std::cout<<test2.at(i)<<"n";
                }
                catch(const std::out_of_range&)
                {
                    throw i;
                }
            }
        }
    }
    virtual void bar()
    {
    }
    std::map< int, float > test2;
    std::map<int, std::string> test;
};
class B : public A
{
public:
    B()
    {
        test3[6] = 15;
        test3[7] = 42;
        bar();
    }
    void bar()
    {
        int k = -1;
        label:
        try
        {
            foo(k);
        }
        catch(int i)
        {
            try
            {
                std::cout<<test3.at(i)<<"n";
            }
            catch(const std::out_of_range&)
            {
                k = i;
                goto label;
            }
        }
    }
std::map<int, int> test3;
};

打印

three
5.55
five
15

而不是

three
5.55
five
15
42

我正在尝试做的是迭代包含不同数据类型的地图,这些地图不能保存在一个容器中,这就是我想出的

我的理解是,你需要的是:

  • 您希望通过一定范围的键打印不同映射中包含的所有值。
  • 地图具有不同类型的值。并非所有键都存在于所有映射中。
  • 派生类可能包含其他映射。

与其使用这种复杂的 exception+goto 设计,为什么不使用基于虚拟方法的更简单的设计来打印特定值:

class A {
public:
    virtual void showValue(int key) {
        if (map1.count(key))
            std::cout << map1[key];
        else if (map2.count(key))
            std::cout << map2[key];
    }
    void showAll() {
        for (int i=0; i<=7; i++)
            showValue(i);
    }
    std::map<int, float> map1;
    std::map<int, std::string> map2;
};
class B : public A {
public:
    virtual void showValue(int key) {
        if (map3.count(key))
            std::cout << map3[key];
        else
            A::showValue(key);
    }
    std::map<int, int> map3;
};

正在发生的事情是,当您打印 15 时,您throw i .这不会被捕获,并逃逸到:

   catch(int i)
    {
        try
        {
            std::cout<<test3.at(i)<<"n";
        }
        catch(const std::out_of_range&)
        {
            k = i;
            goto label;
        }
    }

该号码已正确打印在那里,但不会重新启动。在不知道更多细节的情况下,弄清楚如何解决它几乎是不可能的......

更好的解决方案如下所示:

for (int i=0;i<=7;i++)
{
    if (test.find(i)!=std::map::end)
      std::cout<<test.at(i)<<"n";
    else if (test2.find(i)!=std::map::end)
      std::cout<<test2.at(i)<<"n";
    else if (test3.find(i)!=std::map::end)
      std::cout<<test3.at(i)<<"n";
    else
      std::count<<"Nothing Found"<<std::endl;
}