2015-07-21 90 views
-1

我有兩個類BaseJob和DerivedJob,然後我與它的工作的一些代碼:C++如何使用繼承

Beanstalkpp::BaseJob* Beanstalkpp::Client::reserve() { 

    if (something) 
    { 
     return new ExtendedJob(some_data); 
    } 
    if (something_else) 
    { 
     return new SpecialJob(some_data); 
    } 
} 

我想用它喜歡:

ExtendedJob *j = client.reserve() 

但到目前爲止,我越來越:

error: invalid conversion from ‘Beanstalkpp::BaseJob*’ to ‘Beanstalkpp::ExtendedJob*’ [-fpermissive] 

更新:

class BaseJob 
{ 
    ... 
} 

class ExtendedJob : public BaseJob 
{ 
    ... 
} 

更新2: 如此,因爲很多答案說,這是不可能的,或者,如果是的話,做一些危險的,我想更多的描述我嘗試解決。

我對工作的一些基本功能與類似工作:

BaseJob reserve() 
void del(BaseJob& j) 
void bury(BaseJob& j) 
... 

然後,我有一些工作clases像ExtendedJob,SpecialJob所有延伸BaseJob。上面提到的所有函數都會執行相同的操作(會調用對象的相同函數調用)。

所以我看到2種方式解決我的問題

  • 對於每個作業類型,我將創建一個像reserveBaseJob(),reserveSpecialJob()自定義函數的...
  • 對於每一個功能,我將創造同樣的功能但作爲模板,然後函數每次調用將包含類的名稱,如:德爾()

所有作業類實現相同的接口....

+4

什麼是繼承層次?模板來自哪裏? –

+0

@FredLarson對不起,我刪除了模板並添加了層次結構 –

回答

0

這不是p因爲你永遠不能確定你的client.reserve()創建ExtendedJob,而不是SpecialJob或其他任何東西。考慮你的代碼如何運行,如果reserve()創建SpecialJobSomeOtherUnrelatedJob,但你試圖將它保存到指針ExtendedJob

如果你確信reserve()總是創建ExtendedJob或它的子類無論它是從調用,然後改變其聲明返回ExtendedJob*

如果你確信reserve()總是創建ExtendedJob或它的子類時,它從特定的地方叫,然後你可以使用dynamic_cast,但無論如何這種味道不好的設計。

+0

所以基本上我所要做的就是創建像reserveExtendedJob(),reserverSpecialJob(),reserveSomeOtherJob()等功能吧? –

+1

@DusanPlavak,這個我不能說,因爲這很大程度上取決於你的架構。無論如何,一堆這樣的功能似乎並不合適。也許它會是一個模板化的功能,或者你會改變你的設計並完全避免它。 – Petr

0

這是因爲您隱式地將基類類型轉換爲派生類類型。爲此,使用dynamic_cast<T>

ExtendedJob *j = dynamic_cast<ExtendedJob*>(client.reserve()); 

這將產生NULL如果轉換不能進行,例如,因爲該指針是另一種類型的層次結構。

0

此錯誤的原因是該函數的返回類型是Beanstalkpp::BaseJob*。所以,當你返回ExtendedJob*時,它隱含地鑄造成BaseJob*

然後,在您的程序代碼中,您要從基指針向下傾向ExtendedJob*,這很危險,因爲它也可以是SpecialJob*。如果您希望指針會ExtendedJob*,你可以嘗試明確的轉換非常謹慎:

ExtendedJob* j = dynamic_cast<Beanstalkpp::ExtendedJob*>(client.reserve()); 
if (NULL != j) { 
    // your code here 
} 
0

如果可能的話,我建議做這樣的:

BaseJob* j = client.reserve(); 

,包括插入到BaseJob中一些由ExtendedJob覆蓋的虛擬方法。

0

假設BaseJobExtendedJobSpecialJob基類,你應該做的:

BaseJob * j = client.reserve(); 

你得到的錯誤意味着你想BaseJob(的reserve()返回類型)轉換爲一個它的孩子。編譯器無法確定這一點,所以會引發錯誤。一個dynamic_cast<ExtendedJob*>將強制這個轉換,但它通常不是一個好設計。

0

派生到基類的轉換是可能的。但是,這種轉換,即派生到基類轉換在您的代碼中沒有看到。你面臨的問題是,你做的派生類點的指針,它的基類的位置:

ExtendedJob *j = client.reserve() 

的問題是,ExtendedJob將指向BaseJob對象的一部分(即ExtendedJob的成員) 。但是沒有這樣的成員,因此編譯器會標記錯誤。

修復是使用的dynamic_cast

ExtendedJob *j = dynamic_cast<ExtendedJob*>(client.reserve())