C ++中用于对象构造的**习语

时间:2010-06-08 22:30:28

标签: c++ factory construction

在许多C ++ API中(基于COM的那些)让你想到 make 的东西,指向构造对象的指针通常需要作为**指针(并且该函数将为您构造并初始化它)

您通常会看到以下签名:

HRESULT createAnObject( int howbig, Object **objectYouWantMeToInitialize ) ;

- 但您很少看到新对象作为返回值传递。

除了想要查看错误代码的人,这是什么原因?使用**模式而不是返回的指针更简单的操作,例如:

wchar_t* getUnicode( const char* src ) ;

或者这更好地写成:

void getUnicode( const char* src, wchar_t** dst ) ;

我能想到的最重要的事情就是记住释放它,**方式,出于某种原因,往往会提醒我,我必须解除它。

7 个答案:

答案 0 :(得分:11)

“除了想要错误代码”?

是什么让你认为 a。错误代码几乎是唯一的原因。该功能需要某种方式来指示失败。 C没有异常,因此必须通过指针参数或返回值来执行此操作,并且返回值是惯用的,并且在调用函数时更容易检查。

(顺便说一句,没有通用规则**意味着你必须释放对象。情况并非总是如此,并且使用任意的东西来提醒你哪些对象可能是个坏主意清理。)

答案 1 :(得分:2)

我想到了两个原因。

首先是实际的错误代码。除了C ++之外,C没有例外,COM是C-API。此外,许多基于C ++的项目不希望出于各种原因使用异常。 可能存在返回值不能表示错误的情况,例如。如果函数返回一个整数,则可能没有整数值,可以表示错误代码。虽然指针的信号错误很容易(NULL == Error),但一些API设计人员更愿意以一致的方式在所有函数上发出错误信号。

其次,函数只能有一个返回值,但调用它们可能会创建多个对象。如果使用非NULL指针调用这些函数,某些Win32 API函数会接受指向可以任意填充的指针的多个指针。如果返回值是包含多个指针的值的某个struct,则不能返回两个指针,或者更难以使用它。在这里,一致的API也是一个明智的目标。

答案 2 :(得分:1)

**传递的函数参数中的新对象更好。这使我对将来使用变更voidbool感到安慰,例如,为了返回函数或其他提供函数工作的信息的成功。

在一行中回答:这对于产生的错误代码要好得多。

答案 3 :(得分:1)

  

除了想要查看错误代码的人之外,原因是什么?

这有一些原因。其中一个是编写一个可在C中使用的接口(你在WinAPI和Windows COM中看到这个)。

向后兼容性是另一个原因(即接口是这样编写的,现在打破它会破坏现有代码)。

在使用这样的代码时,我会使用C兼容性来设计原则。如果你用C ++编写,你会写

retval Myfunction(Result *& output);

而不是

retval Myfunction(Result ** output);

或(甚至更好):

Result *Myfunction();

并让函数在出错时抛出异常。

答案 4 :(得分:0)

我不确定我是否认为这是最好的方法......这可能会更好:

Object * createAnObject(int howbig, HRESULT * optPlaceResultCodeHereIfNotNull = NULL);

这样就没有任何关于双向间接的问题(对于那些不习惯它的人来说可能有点棘手),不关心结果代码的人不必担心关于第二个参数......他们可以检查返回值是否为NULL。

实际上,由于它是C ++,你可以使用函数重载使事情变得更容易:

Object * createAnObject(int howbig);
Object * createAnObject(int howbig, HRESULT & returnResultCode);

答案 5 :(得分:0)

COM调用中的任何方法调用都必须 HRESULT。返回代码在整个框架中得到充分利用,并且传递双指针是获取创建对象的众所周知的方法。

答案 6 :(得分:0)

没有回答你的问题而是评论,因为你的问题引出了一些关于使用C ++进行COM / DCOM编程的想法。

所有这些“指针”和“指向指​​针”,内存管理和引用计数是我回避用C ++进行COM编程的原因。即使使用ATL,我也不喜欢它,原因很简单,因为它看起来不够自然。话虽如此,我确实使用ATL做了一些项目。

当时替代方案是使用VB。对于COM或DCOM编程,VB代码看起来更自然。

今天,我会使用C#。