Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何创建一个构造函数(c+;+;),在失败时创建一个空对象?_C++_Initialization - Fatal编程技术网

C++ 如何创建一个构造函数(c+;+;),在失败时创建一个空对象?

C++ 如何创建一个构造函数(c+;+;),在失败时创建一个空对象?,c++,initialization,C++,Initialization,我如何创建一个构造函数(c++),在它失败时创建一个空对象 我想创建一个行为类似于库中的类的类 #包括支持彩色图像所需的“diregist.h”/**/ DicomImage*图像=新的DicomImage(“test.dcm”); 如果(图像!=NULL) { 如果(图像->获取状态()==EIS\U正常) { Uint8*像素数据=(Uint8*)(图像->获取输出数据(每个样本8/*位*); if(像素数据!=NULL) { /*对像素数据做一些有用的事情*/ } } 其他的 cerr不

我如何创建一个构造函数(c++),在它失败时创建一个空对象

我想创建一个行为类似于库中的类的类

#包括支持彩色图像所需的“diregist.h”/**/
DicomImage*图像=新的DicomImage(“test.dcm”);
如果(图像!=NULL)
{
如果(图像->获取状态()==EIS\U正常)
{
Uint8*像素数据=(Uint8*)(图像->获取输出数据(每个样本8/*位*);
if(像素数据!=NULL)
{
/*对像素数据做一些有用的事情*/
}
} 
其他的

cerr不容易。您可以在DicomImage类的声明中重写
DicomImage::operator new()
。然后可能失败并返回NULL的实际逻辑将进入operator new()中主体,而不是实际的构造函数。一旦进入构造函数,返回NULL为时已晚,此时对象已经创建。问题是运算符new()没有收到构造函数参数,因此您可能没有失败所需的信息

另一种方法是让factory方法或factory类实际创建您的实例,因此您的代码如下所示:

DicomImage* pImage = CreateDicomImage( "stuff" );

不过,因为你的问题中有“异常处理”,并且至少要让答案更适合程序员SE(而不是StAdExtRoad)问题,所以我想指出你可以并且应该利用C++中的异常处理。


当返回NULL时,您将强制所有客户端代码在调用new DicomImage()之后立即添加错误检查逻辑,这会降低可读性,因为错误检查最终会与实际应用程序逻辑混合

如果代码看起来像:

std::unique_ptr< DicomImage > pImage( new DicomImage( "stuff" ) );
pImage->DoSomeCommand();
pImage->DoSomeOtherCommand();
std::unique_ptrpImage(新的DicomImage(“东西”);
pImage->DoSomeCommand();
pImage->DoSomeOtherCommand();
…而且不必担心“如果”如果创建失败,则可以通过使用C++异常处理来实现这一点,如果创建失败,则构造函数会抛出异常。安装程序尝试在处理此块的代码块周围捕获块,而在该块中所包含的是纯应用逻辑。通用电气的创新失败了


…通过使用智能指针,您还可以保证,如果以后出现任何故障,pImage将始终被删除。因此,您无需担心在退出函数之前必须调用delete。

我认为构造函数无法做到这一点-此url表示构造函数不能返回null

可能有“黑客”行为,但可能不合法 您可能已经知道所有这些,但以防万一: (1) 构造函数无法返回值,并且 (2) 我认为它无法控制分配给该实例的内存 调用构造函数,但构造函数可以将类成员设置为空值

此URL有一个变通方法-如果您确实需要使用NULL(不推荐) 使构造函数私有并使用“工厂方法”(函数):

我知道这和你的问题是分开的,但我只是想 确保有人知道有关新的编译器行为:

根据这个URL,最新的编译器是 不应使用新运算符返回NULL(是 应该抛出一个异常),尽管 允许较旧的编译器执行此操作:


使用DicomImage的代码与您认为的不一样

示例代码

if (image != NULL)
{
是针对无异常环境的防御性编程,当系统内存不足时返回NULL

启用异常时,new将抛出内存不足异常。如果禁用异常,则new将返回NULL

为了回答您的问题,构造函数不能返回NULL

class Foo
{
public:
    static Foo* MakeFoo()
    {
       Foo* foo = NULL;
       if (LifeIsGood())
           foo = new Foo();
       return foo;
    }
private:
    Foo();
};

Foo* myFoo = Foo::MakeFoo();
if (myFoo)
    BeFooish(myFoo);
但是,静态工厂方法可以返回NULL

class Foo
{
public:
    static Foo* MakeFoo()
    {
       Foo* foo = NULL;
       if (LifeIsGood())
           foo = new Foo();
       return foo;
    }
private:
    Foo();
};

Foo* myFoo = Foo::MakeFoo();
if (myFoo)
    BeFooish(myFoo);

您不能,并且根据DicomImage的文档判断,您确实不想模拟该类的接口。

使用new()运算符执行此操作并不是重写new()的真正目的运算符。从您的示例中,我不确定您是否允许更改客户端代码;但是,如果您可以控制客户端代码,则只需使用工厂方法,其中您将使用构造函数:

class Foo {

  Foo(int arg) {...}

  static Foo *new_Foo(int arg) {
    if (! I_like(arg)) return null;
    return new Foo(arg);
  }

}

// ...
// in the client

Foo *foo =
// nope:
// new Foo(3);
// do this instead:
Foo.new_Foo(3);

在对象创建中不能返回null,但是可以更改运算符==和的行为= 试试下面的代码,我还没有试过

bool MyClass::operator==(const MyClass &other) const {
    if(&other == null){
        if(/* your validations */){
            return true;//it is null
        }else{
            return false;//
        }       
    }
    return (*this == other);//it is not compare with null
}
bool MyClass::operator!=(const MyClass &other) const {
    if(&other == null){
        if(/* your validations*/){
            return true;//is not null
        }else{
            return false;
        }       
    }
    return !(*this == other);//it is not compare with null
}

如果有人在NoFlash内存不足的情况下,为什么要制作<代码>新的<代码>返回null?为什么不抛出异常或其他更合适的错误处理?从构造函数中抛出异常是危险的。@ StvnBeNAP:这取决于语言和编译器。人们过去常说,使用C++编译器是危险的,因为它们使用了。在抛出异常时泄漏内存。但这已经被修复很久了,只要您的API有文档记录并且调用方知道异常,在构造函数中使用它们应该不会比在正常调用中使用它们更危险。@StevenBurnap:不太危险。首先,如果您直接在构造函数中使用
new
,并且
成员
不负责释放
对象
,你是个白痴。如果
成员
负责释放
对象
,那么在所有情况下,
成员
的工作就是清理
对象
。如果不违反所有权语义,你就不会有这个问题。@StevenBurnap:Rucor是C++中构造函数中错误处理的正确方法。在下一个注释中,您的示例是假的。它不会泄漏,因为任何动态分配的成员都将被保存在智能指针 STD::AutoMyPTR成员;中,因此不会泄漏。如果您没有使用智能指针。