【问题标题】:C++ class constructor throwing an exceptionC++ 类构造函数抛出异常
【发布时间】:2014-11-03 13:48:52
【问题描述】:

让我们考虑有一个 class 和一个 constructor 抛出一个异常 em> 如下:

class Class
{
    public:
        Class(type argument)
        {
            if (argument == NULL)
            {
                throw std::exception("Value cannot be null.\nParameter name: argument");
            }

            // Instructions
        }
    private:
        // Properties
}

由于 构造函数可能会抛出异常 我们不能直接声明一个对象

Class obj(argument); // Harmful

这意味着必须调用 构造函数 必须使用 try/catch

try
{
    Class obj(argument);
}
catch (std::exception& ex)
{
    std::cout << ex.what() << std::endl;
}

问题是我们只能在 try 块中使用 object。在 try 块之外使用它的唯一方法是声明一个 Class* pointer 然后使用 new 关键字构造一个新的 object 然后将其地址分配给前一个 指针

Class* pObj;

try
{
    pObj = new Class(argument);
}
catch (std::exception& ex)
{
    std::cout << ex.what() << std::endl;
}

那么定义先前的以便在不使用指针的情况下创建实例的标准方法是什么还是动态内存分配?

提前致谢

【问题讨论】:

  • 如果您使用指针方法并且构造函数抛出,您可以捕获异常并仍然访问 try-catch 块之外的指针。但是现在呢?你有一个指针但没有对象!异常的目的不是包装每个最终可能会在 try-catch 块中抛出的语句,从而再次线性化控制流。发明异常是为了允许相反的情况:在异常情况下(例如在错误地将 NULL 指针传递给不接受的构造函数之后)打破正常的控制流。
  • 如果我没记错的话,我在某个地方看到这不是一个真正好的设计。因此,您应该怎么做才能毫无例外地创建它,并检查它是否已正确创建。
  • 如果您不喜欢异常但更喜欢传统的错误处理,那么就这样做吧。但是,如果您将函数设计为抛出异常(我更喜欢这样做),那么之后不要与该机器作斗争。传递了无效参数的构造函数引发的异常应该 (§ 22)“破坏”程序。 (如果您希望程序继续运行,请不要传递无效参数。)
  • 如果我没记错的话,标准 std::exception 没有将 const char* 作为参数的构造函数。
  • 可能想要std::runtime_error

标签: c++ class exception constructor


【解决方案1】:

由于类构造函数可能会抛出我们无法声明的异常 直接一个对象。

是的,你可以。如果您确实有计划在函数中处理异常,则只需将其放入 try 块中。如果您没有这样的计划,那么就让异常传播(尽管您最终应该捕获它,只是为了提供报告,如果没有别的)。

但是,假设您确实有计划在函数中处理异常,那么解决方案很简单。

try {
    Class obj(argument);
    // use obj here, inside the try block
}
catch(...) { ... }

// not here, outside the try block

编辑:通过您在下面的评论,要么您误解了我,要么我误解了您。也许需要一个具体的例子。假设这是使用您的类的函数:

void Foobar(type argument)
{
    Class obj(argument);
    obj.method1(1,2,3);
    obj.method2(3,4);
    int x = Wizbang(obj);
    gobble(x);    
}

现在,您要处理Class 构造函数可能抛出的异常。我的建议是将函数中的所有垃圾放入 try 块中,因此:

void Foobar(type argument)
{
    try
    {
        Class obj(argument);
        obj.method1(1,2,3);
        obj.method2(3,4);
        int x = Wizbang(obj);
        gobble(x);
    }
    catch(std::exception& e)
    {
        std::cout << e.what() << std::endl;
    }
}

如果您不能这样做,请解释原因。你说过“我需要访问权限才能稍后使用该对象”,但你没有提供为什么 “later” 不能表示 “later 在同一个尝试创建对象的块”。因此,您的要求不完整。

【讨论】:

  • @cell:如果他这样做了,那么他当然没有提供任何应该取消该选项的理由。
  • 当我说我不能时,我的意思是如果抛出异常,程序就会爆炸。在 try/catch 中创建对象不是一个选项,因为我以后需要访问才能使用该对象。
  • @rullof:具体来说,您需要在哪里使用该对象?确切地说,为什么您需要使用它的代码不在 try 块中?
  • @rullof,事情就是这样。如果对象创建成功,则可以安全使用。如果没有,则无法安全使用。离开 try 块意味着对象没有成功创建。考虑到这一点,使用该对象并不好。
【解决方案2】:

你想要的不是(合理地)可能的。假设有一些方法可以做你想做的事,即创建一个 Class 类型的对象 obj,它仍在用于处理构造函数中异常的任何相关 try{}catch{} 构造之外的范围内。要问自己的问题是,如果在构造 obj 期间抛出异常,并且您以某种方式处理了异常,然后在 obj 仍在范围内的块中继续执行,那么 obj 究竟包含什么?它从未被构建过,那么 obj 中会是什么????

【讨论】:

    猜你喜欢
    • 2017-02-09
    • 2019-03-11
    • 2023-03-11
    • 2018-05-21
    • 2011-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多