什么是最好的技术退出构造函数在C ++中的错误条件 [英] What's the best technique for exiting from a constructor on an error condition in C++

查看:228
本文介绍了什么是最好的技术退出构造函数在C ++中的错误条件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在C ++中的错误条件下,从构造函数退出的最好的技术是什么?特别是,这是一个打开文件的错误。



感谢您的回复。我抛出一个异常。这里是代码(不知道是否是最好的方法,但它很简单)

  //测试以查看文件是否已打开;否则
if(!file.is_open()){
cerr<< 无法打开文件:< m_filename<< endl;
throw(无法打开文件);
}

我认为我喜欢C ++是你不必声明抛出异常对方法声明。

解决方案

最好的建议是parashift说。但请仔细阅读我的注意事项。



参见parashift FAQ 17.2


[17.2]如何处理失败的构造函数
? >

抛出异常



构造函数没有返回类型
,因此无法使用return
codes。信号
构造函数失败的最好方法是让
抛出异常。如果你没有
使用异常的选项,
最差的解决方法是通过

对象置于僵尸状态内部状态位,所以
对象的行为类似它死了
即使它在技术上仍然是
活着。



一个僵尸对象有一个
很多下侧。你需要添加一个
查询(inspector)成员函数到
检查这个zombie位,所以用户的
你的类可以找出他们的
对象是否真的活着,或者如果它是一个
僵尸(即,一个活死对象),
和几乎每个地方你
构造你的对象之一
(包括在一个更大的对象或
对象数组),你需要通过if语句检查
的状态标志。
你还要在你的
其他成员函数中添加一个if:如果对象
是一个僵尸,做一个no-op或者可能
一些更讨厌的东西。 / p>

在实践中,僵尸的事情得到
很丑陋。当然你应该
喜欢比僵尸对象的异常,
但是如果你没有使用异常的选项
,僵尸对象可能
是最差的替代。 p>






在构造函数中抛出异常的谨慎:



要非常小心,因为如果一个异常抛出在构造函数中,类的析构函数不会被调用。因此,在抛出异常之前,您需要小心处理已经构建的对象。相同的警告一般适用于异常处理,但在处理构造函数时可能不太明显。

 类B 
{
public:
B()
{

}

virtual〜B
//在D的构造函数异常之后调用
}
};

class D:public B
{
public:
D()
{
p = new char [1024]
throw std :: exception(test);
}

〜D()
{
delete [] p;
//从未调用,因此p导致内存泄漏
}

char * p;
};

int main(int argc,char ** argv)
{

B * p;
try
{
p = new D();
}
catch(...)
{

}


return 0;
}

使用CreateInstance方法的受保护/私有构造函数 / p>

另一种方法是使你的构造函数为private或protected,并创建一个可返回错误的CreateInstance方法。


What's the best technique for exiting from a constructor on an error condition in C++? In particular, this is an error opening a file.

Thanks for the responses. I'm throwing an exception. Here's the code (don't know if it's the best way to do it, but it's simple)

// Test to see if file is now open; die otherwise 
if ( !file.is_open() ) {
    cerr << "Failed to open file: " << m_filename << endl;
    throw ("Failed to open file");
}   

One think I like about C++ is you don't have to declare thrown exceptions on the method declarations.

解决方案

The best suggestion is probably what parashift says. But read my caution note below as well please.

See parashift FAQ 17.2

[17.2] How can I handle a constructor that fails?

Throw an exception.

Constructors don't have a return type, so it's not possible to use return codes. The best way to signal constructor failure is therefore to throw an exception. If you don't have the option of using exceptions, the "least bad" work-around is to put the object into a "zombie" state by setting an internal status bit so the object acts sort of like it's dead even though it is technically still alive.

The idea of a "zombie" object has a lot of down-side. You need to add a query ("inspector") member function to check this "zombie" bit so users of your class can find out if their object is truly alive, or if it's a zombie (i.e., a "living dead" object), and just about every place you construct one of your objects (including within a larger object or an array of objects) you need to check that status flag via an if statement. You'll also want to add an if to your other member functions: if the object is a zombie, do a no-op or perhaps something more obnoxious.

In practice the "zombie" thing gets pretty ugly. Certainly you should prefer exceptions over zombie objects, but if you do not have the option of using exceptions, zombie objects might be the "least bad" alternative.


A word of caution with throwing exceptions in a constructor:

Be very careful though because if an exception is thrown in a constructor, the class's destructor is not called. So you need to be careful about destructing objects that you already constructed before the exception is thrown. The same warnings apply to exception handling in general, but it is maybe a little less obvious when dealing with a constructor.

class B
{
public:
    B()
    {

    }

    virtual ~B()
    {
        //called after D's constructor's exception is called
    }
};

class D : public B
{
public:
    D()
    {
        p = new char[1024];
        throw std::exception("test");
    }

    ~D()
    {
      delete[] p;
      //never called, so p causes a memory leak
    }

    char *p;
};

int main(int argc, char **argv)
{

    B *p;
    try
    {
        p = new D();
    }
    catch(...)
    {

    }


    return 0;
}

Protected/Private constructors with CreateInstance method:

Another way around this is to make your constructor private or protected and make a CreateInstance method that can return errors.

这篇关于什么是最好的技术退出构造函数在C ++中的错误条件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆