2010-07-05 89 views
1

與生產中存在的代碼類似。你們能否回顧一下,告訴我這些代碼是否能夠一直運作良好?評論此C++代碼

class Base 
{ 
    public: 
     virtual void process() = 0; 
}; 

class ProductA : public Base 
{ 
    public: 
    void process() 
    { 
     // some implementation. 
     doSomething(); 
    } 

    void setSomething(int x) 
    { 

    } 

    virtual void doSomething() 
    { 
     // doSomething. 
    } 

}; 

class ProductANew : public ProductA 
{ 
    public: 
     ProductANew() : ProductA() { } 
     void doSomething() 
     { 
      // do Something. 
     } 
}; 


int main(int argc, char *argv[]) 
{ 
    Base* bp = new ProductANew(); 
    dynamic_cast<ProductA*>(bp)->setSomething(10); 
    bp->process(); 
} 
+3

我猜'class ProductA'的定義實際上應該從'class ProductA:public Base'開始。 – 2010-07-05 10:13:12

+1

您的擔心是什麼 - 動態轉換?這些來自/爲什麼不能使用ProductA *而不是Base * - 您是否將ProductA存儲在通用陣列或類似的數據中? – Rup 2010-07-05 10:13:43

+0

那裏有一個具體的問題,就像dynamic_cast的這種使用總是工作等等?對於記錄,如果RTTI不適合,dynamic_cast可能會給你一個空指針,而你不需要檢查就直接解引用。但是,如果這實際上是你的生產代碼,並且在這種實例化之後立即執行轉換,那麼你沒有什麼可擔心的。哦,而且您的ProductA不會從Base繼承... – falstro 2010-07-05 10:14:16

回答

7

有了好的設計,你不會需要一個dynamic_cast。如果process()不能在未致電setSomething()的情況下調用,則應該將它們暴露在相同的基類中。

+0

是的..這是我期待的評論評論之一。謝謝。 – Jagannath 2010-07-05 10:21:14

+0

一個很好的設計是什麼?是 - 只是一個瘋狂的猜測 - Base的子類將封裝算法的實現,然後這些對象將被安排爲一個進程的網絡?如果是這樣的話,在基本接口上暴露doSomething()的尖銳建議對我來說不是一個好主意... – miquelramirez 2010-07-05 12:23:01

+0

@miquelramirez,如果setSomething(int x)是什麼基本方法的一部分,並提供了一個默認的實現?我們不需要一個dynamic_cast產品的權利。 – Jagannath 2010-07-05 14:21:56

19

一些問題:

  • 基類必須有一個虛析構函數
  • 你永遠不刪除的對象的新
  • 分配你從來沒有測試的dynamic_cast的結果
1

通常你會發現那些甚至無法編譯的代碼是非常糟糕的設計。

Base* bp = new ProductANew(); 

此行不能工作,因爲ProductANew不以任何方式,形狀或形式從Base繼承。

$ gcc junk.cc 
junk.cc: In function ‘int main(int, char**)’: 
junk.cc:41: error: cannot convert ‘ProductANew*’ to ‘Base*’ in initialization 

(只要是明確的:junk.cc包含你的代碼剪切並粘貼)


編輯補充...

遲到者可能想看看投票前原始問題的歷史。 ;)

+4

-1'刪除'按鈕可以用來刪除虛假答案,這樣人們的時間不會花費在閱讀它們。 – 2010-07-05 11:02:35

3

有一個實際的錯誤和一堆危險/問題的做法:


的一個錯誤是,你永遠叫deletenew版的對象,所以它泄漏。


問題的做法:

  1. Base沒有虛析構函數,因此,如果您通過調用delete或使用auto_ptr糾正錯誤,你會調用未定義的行爲。
  2. 根本沒有必要使用動態分配。
  3. 多態基類應該是不可複製的,以防止對象切片。
  4. 您在使用dynamic_cast而不需要檢查結果 - 爲什麼不只是聲明bp作爲指向ProductANewProductNew的指針呢?
  5. ProductANew不需要一個構造函數 - 默認的就可以了。

其中幾點可能是你的例子的性質的結果 - 即你有充分的理由使用動態分配,但你想保持你的例子小。

+0

IIRC,在大多數平臺上,應用程序的堆在終止時會自動釋放。因此,絕對不推薦刪除'delete',但本身不是錯誤,並且不一定會導致泄漏。 – Mac 2010-07-06 04:01:59

+0

我仍然認爲任何在程序結束時沒有被銷燬的對象都是錯誤的 - 但是你是對的,在任何現代的消費者環境中,這不是一個問題,除非對象擁有一些其他的操作系統資源無法爲你清理。 – 2010-07-06 07:23:01