2010-06-08 32 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(); 

,並有功能扔在錯誤的異常。