2011-02-18 57 views
0

我在C++項目中使用C編寫的庫。對C指針使用std :: bad_alloc

我想使用C++異常來處理C錯誤。尤其是,如果分配失敗,那麼拋出異常將會很好。

if (c_object == NULL) 
    throw std::bad_alloc(); 

但如果類負責幾個C的對象,他們是沒有自由荷蘭國際集團都已經分配的方式:

我可以在類的構造函數持有C風格的指針C的結構做因爲析構函數沒有被調用,所以指針。

我有一種感覺,我可以使用智能指針,但我沒有太多的經驗與他們。更重要的是,我必須有權訪問原始C指針才能正確使用C api。

有沒有一個優雅的解決方案呢?

+6

C++ RAII(資源獲取是初始化),每個類只管理1個資源。 – 2011-02-18 15:12:12

+1

如果我這樣做,我基本上最終會爲C庫編寫一個C++包裝器。我跳了一個更簡單的解決方案:/ – fouronnes 2011-02-18 15:16:40

回答

3

它在評論中已經述及,我只是重複了一個答案:

但如果類負責幾個C的對象,他們沒有免費的-ING所有的方式已經因爲不調用析構函數,因此分配了指針。

這是正確的。由於這一點和單一責任原則,每個C++類至多管理一個非託管資源(在您的案例中爲「C對象」)。那些管理資源的類絕對沒有別的。

如果您使用智能指針,您完全可以這樣做:智能指針類管理對單一資源類型的訪問,即通常以new(後者可以自定義)分配的堆對象。如果這對你有幫助,可以隨意使用智能指針,這是完全正確的,但從不寫一個管理多個原始資源的類。

1

我認爲你試圖平凡地實現基本上不可實現的。 在任何情況下,我認爲這是最好的以下兩種方法

  1. 每個結構之間作出選擇,寫一個C++包裝沒有例外
  2. 後續Ç方法(如現在)

我不要以爲你可以沒有其他選擇的努力2 :)

HTH

2

爲什麼你不能使用實現1的效果塊在構造函數中?

A::A() : c_object(0), c1_object(0), c2_object(0) 
{ 
    try 
    { 
     c_object = getCObject(); 
     if (!c_object) 
     throw std::bad_alloc(); 
     c1_object = getCObject1(); 
     if (!c1_ojbect) 
      throw std::bad_alloc(); 
     //..... 
    } 
    catch (std::bad_alloc&) 
    { 
     if (c_object) 
      releasCObjectMemory(c_object); 
     if (c1_object) 
      releasCObjectMemory(c1_object); 
     //.... 
     throw; 
    } 
} 
3

您可以將每個指針存儲在智能指針中,如shared_ptr。那些還接受(可選)指向釋放函數的指針。

要拋出異常,你可以包裝每個分配函數。

//the api functions 

Foo* CreateFoo(Bar); 

void DestroyFoo(const Foo*); 

//wrapped with 
boost::shared_ptr<Foo> CppCreateFoo(Bar bar) 
{ 
    boost::shared_ptr<Foo> new_foo(CreateFoo(bar), &DestroyFoo); 
    if (!new_foo) { 
     throw std::bad_alloc(); 
    } 
    return new_foo; 
} 

//underlying pointer accessed with 
boost::shared_ptr<Foo> smart_foo_ptr = CppCreateFoo(bar); 
UseFooPtr(smart_foo_pointer.get());