2010-06-08 157 views
0

在很多C++ API(基于COM的语言)中,使成为某种东西,指向构造对象的指针通常需要作为**指针(该函数将建立和初始化它你)用于构建对象的C++语言的成语

大家平时看到的签名一样:

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

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

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

wchar_t* getUnicode(const char* src) ; 

还是会这更好的可以写为:

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

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

+4

对我来说看起来像C。在C++中,它们只是将其作为参考传递或抛出异常。 – 2010-06-08 22:35:47

+0

为什么这么多的答案注重COM ..?这仅仅是它使用的一个例子 - 它也用在许多其他C-API中,例如FMOD。 – bobobobo 2010-06-09 00:31:30

回答

11

“除了想要错误代码”?

是什么让你觉得有另外。错误代码几乎是唯一的原因。该功能需要某种方式来指示失败。 C没有例外,所以它必须通过指针参数或返回值来实现,并且返回值是惯用的,并且在调用函数时更容易检查。 (顺便说一下,**意味着你不得不释放这个对象,这并不总是这样,使用任意的东西来提醒你清理哪些对象可能是一个坏主意。 )

+2

确实你也可以用C语言编写COM编程。 COM的跨语言设计和时代意味着它缺少很多现代C++的东西,比如C++异常。 – 2010-06-08 22:40:28

+0

哦对,我忘了提及那一部分。是的,COM意味着独立于语言和编译器,这意味着它不能依赖于异常(这在某些语言中不存在,甚至在C++中它们确实存在,它们在编译器之间的实现可能会有所不同) – jalf 2010-06-08 22:51:57

1

通过**传递的函数参数中的新对象更好。这对我未来使用变更voidbool以例如返回功能或其他信息提供功能工作的成功感到舒适。

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

0

我不知道我同意这是做到这一点的最好方式......这可能会更好:

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

这样没有摆弄双间接(它可以是一个小对不习惯它的人有点棘手),而不关心结果代码的人根本不必担心第二个参数......他们可以检查返回值是否为NULL或不。

事实上,因为它是C++,你可以让事情变得更容易的是,使用函数重载:

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

顺便说一下,这就是boost.asio的写法 - 所有的东西都被一个抛出boost :: system :: system_error的版本和一个采用boost :: system :: error_code& – Cubbi 2010-06-08 23:05:53

0

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

2

我想到了两个原因。

首先是实际的错误代码。除C++之外,C没有例外,COM是C-API。还有许多基于C++的项目因各种原因而不喜欢使用异常。 有些情况下,返回值不能表示错误,例如,如果你的函数返回一个整数,那么可能没有整数值,它可以表示一个错误代码。尽管用指针发信号错误很容易(NULL ==错误),但是一些API设计者更愿意以一致的方式在所有函数上发出错误信号。

其次,函数只能有一个返回值,但调用它们可能会创建多个对象。如果您使用非NULL指针调用这些函数,某些Win32 API函数会将多个指针指向可以选择填充的指针。你不能返回两个指针,或者,如果返回值是包含多个指针的值的某个结构体,那么这将会使用起来很尴尬。这里一致的API也是一个明智的目标。

0

不回答你的问题,但作为你的问题的评论带出了一些想法,我有关于COM/DCOM编程使用C++的一些想法。

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

当时的选择是使用VB。对于COM或DCOM编程,VB代码看起来更自然。

今天,我会用C#。

1

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

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

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

当使用类似这样的代码时,我会采用C兼容的设计原则。如果你用C写++你会写的

retval Myfunction(Result *& output); 

代替

retval Myfunction(Result ** output); 

或(甚至更好):

Result *Myfunction(); 

,并有功能扔在错误的异常。