【问题标题】:C++, Catching exceptions of different types of dataC++,捕获不同类型数据的异常
【发布时间】:2014-01-03 12:33:23
【问题描述】:

我的问题是我有一个模板类,我尝试捕获不同类型数据(int、float、long、char 等)的异常。

#include <iostream>
using namespace std;

const int MAX = 3;

template<class Type>
class Stack()
{
    class Range{};
    class Empty{};
    class Input{};

    //Code here
    //Code here
    //If Error: 
    throw Range();
    throw Empty();
    throw Input();
}

int main()
{
    try
    {
        Stack<int> s1
        Stack<float> s2
        Stack<long> s3
        Stack<char> s4
    }
    catch(Stack<int>::Range)   { //Code }
    catch(Stack<float>::Range) { //Code }
    catch(Stack<long>::Range)  { //Code }
    catch(Stack<char>::Range)  { //Code }
    catch(Stack<int>::Empty)   { //Code }
    catch(Stack<float>::Empty) { //Code }
    catch(Stack<long>::Empty)  { //Code }
    catch(Stack<char>::Empty)  { //Code }
    catch(Stack<int>::Input)   { //Code }
    catch(Stack<float>::Input) { //Code }
    catch(Stack<long>::Input)  { //Code }
    catch(Stack<char>::Input)  { //Code }

return 0;
} 

我怎样才能在 3 行中做同样的事情? 我试过了:

template <class Type>
catch(Stack<Type>::Range) { }

Error: Expected 'catch' before '<' token       (What's Wrong)


template<class Type>
try { //Code }
catch(Stack<Type>::Range) { }

Error: A template declaration cannot appear at block scope  (Definetely Wrong, I Know)

template<class Type>
int main()
{
    try
    {
        //Code
    }
    catch(Stack<Type>::Range) { }
}

Error: Cannot declare '::main' to be a template   (Of course, That's totally wrong.)

我尝试在很多地方声明“类型”,即使我知道这是错误的。如果我不声明“类型”,那也是错误的。那么,有什么办法可以做到吗?

提前致谢

【问题讨论】:

    标签: c++ templates exception types


    【解决方案1】:

    一般来说,我不确定将异常定义为子类是否是个好主意。至少我没有在任何更大的框架(VCL、.NET、stl,但这并不意味着,当然没有)中看到过。

    我没有针对您的问题的直接解决方案,但如果没有人提供更好的解决方案,您始终可以为所有 Range 异常创建一个基类,并通过基类而不是派生类捕获它们。如果您需要特定类型的功能,您可以随时在基类中创建一个虚拟方法,例如:

    class BaseRangeException
    {
    public:
        virtual void Display() = 0;
    }
    
    template<typename T> RangeException 
    class RangeException : public BaseRangeException
    {
    public:
        void Display()
        {
            // Implement differently, depending on type of template
        }
    }
    

    【讨论】:

    • 实际上,这是一种很好且简单的方法。但是,在这种情况下,您的解决方案要好得多,因为我不必写那么多行……我相信 C++ 的设计者已经预测到了这一点,并且必须有解决方案
    • 嗯,这是我对泛型问题的通用解决方案——创建非泛型基类。但这并不总能解决问题。不过,我不确定您是否可以以通用方式捕获异常。
    【解决方案2】:

    如果我有这样的问题(我想首先通过改变整个代码设计来避免)我可能会尝试做这样的事情:

    template<typename E>
    void TryAndCatch(
        std::function<void (void)> tried,
        std::function<void (const E&) catched>
    ) {
        try {
            tried();
        } catch (const E& exception) {
            catched(exception);
        }
    }
    

    然后像这样使用它:

    TryAndCatch<Stack<int>::Range>(
        []() {
            // tried code in lambda expression
        },
        [](const Stack<int>::Range& exception) {
            // catch code
        }
    );
    

    但是仅仅看一下它就会让我强烈考虑重写代码,这样我就不需要使用它了,例如就像@Spook 建议的那样。

    请注意,模板需要实例化,因此您可以选择要捕获的异常,然后使用模板以某种方式帮助您(也许将代码包装在可以处理它们的模板类中?)或确保一些共同点 - 接口,抽象基类,任君选择。

    【讨论】:

    • 嗯,它太复杂了,但它是我的问题的唯一解决方案......我将异常定义为子类的原因是因为我学会了捕获异常。谢谢
    • 也许您应该尝试创建一些只处理异常的包装器/处理程序?做成模板类,以异常类型和catch函数为参数,间接处理你的代码?
    • 答案应该得到 +1 的评价,因为“但是仅仅看一下它就会让我强烈考虑重写代码,这样我就不需要使用它了”,但这是矛盾的。
    猜你喜欢
    • 2018-01-04
    • 1970-01-01
    • 1970-01-01
    • 2011-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-08
    相关资源
    最近更新 更多