2012-03-08 125 views
1

我有一個家庭作業,其中有一個基類Package和兩個派生類OvernightPackage和TwoDayPackage。在問題的一點上,我需要根據用戶輸入創建這兩種類型中的一種類型的對象。這顯然是行不通的:if語句中的C++範圍問題:創建兩個對象之一

 if (shippingOption == OVERNIGHT) { 
      OvernightPackage packageObject(// Parameters entered here //); 
     } 

     else if (shippingOption == TWODAY) { 
      TwoDayPackage packageObject(// Parameters entered here //); 
     } 

一旦這些if語句執行,我出這些對象的範圍,而不能使用packageObject。 This post幫助我理解如果我只是用不同參數創建某種類型的對象,我該如何做到這一點。但對作業的要求是,TwoDayPackage和OvernightPackage需要不同的類別。

我該如何去做這件事(除了做我需要的與if語句中的對象)?

編輯:感謝您幫助清理事情,每個人!

回答

4

一種方法是使用指針:

Package *packageObject = NULL; 
    if (shippingOption == OVERNIGHT) { 
     packageObject = new OvernightPackage(// Parameters entered here //); 
    } 

    else if (shippingOption == TWODAY) { 
     packageObject = new TwoDayPackage(// Parameters entered here //); 
    } 
+0

太棒了,謝謝!我們剛剛開始繼承,所以我想我對細節有些模糊。這有幫助。 – Nate 2012-03-08 22:02:27

+2

@Nate稍後請不要忘記刪除對象以避免內存泄漏。使用delete pakagheObject; – Topo 2012-03-08 22:05:32

3

A類型的變量實際上不能是派生類型的,所以(如你注意到),你不能只是宣佈Package packageObject;和分配OvernightPackageTwoDayPackage它(它們將被切)。

但是,指向A的指針可指向派生爲A的類的實例。引用和(大多數類型)智能指針也是如此。

+0

太棒了,感謝您幫助明確這一點! – Nate 2012-03-08 22:02:43

+0

引用也是如此,除了你不能指定引用,所以它們在這裏不適用。 – Kaz 2012-03-08 22:05:10

+0

@Kaz:沒錯,我只是爲了完整性而提及它。 – Thomas 2012-03-08 22:07:34

2

像這樣

#include <memory> 
::: 

std::unique_ptr<Package> package; 

if(shippingOption == OVERNIGHT) 
    package.reset(new OvernightPackage(params)); 
else if (shippingOption == TWODAY) 
    package.reset(new TwoDayPackage(params)); 

package->member; 
package->member_function(); 

如果您沒有訪問C++ 11(參見你的編譯器),你可以隨時使用boost::scoped_ptr或如果你真的要std::auto_ptr。 (如果你有gcc/g ++然後嘗試使用-std = C++ 0x進行編譯)

那麼這樣做比其他列出的方法更有優勢在於內存由RAII語義管理,這與現代C++設計。

http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization

http://en.cppreference.com/w/cpp/memory/unique_ptr

http://en.cppreference.com/w/cpp/memory/auto_ptr

2

答案是指針。

Package *packageConstructor(int type) 
{ 
    switch (type) { 
    case OVERNIGHT: return new OvernightPackage(/* ... */); 
    case TWODAY: sleep(2 * 86400); /* :) :) :) */ return new TwoDayPackage(/* ... */); 
    default: // unrecognized type: handle somehow: return NULL, or throw exception 
    } 
} 

一旦你有指針,你必須擔心異常安全。最好使用一些智能指針容器而不是原始指針。

+0

必須+1睡2天。在那裏也有答案,所以沒有缺點:p – chris 2012-03-08 22:44:23

2

運算代碼:

if (shippingOption == OVERNIGHT) { 
    OvernightPackage packageObject(// Parameters entered here //); 
} 
else if (shippingOption == TWODAY) { 
    TwoDayPackage packageObject(// Parameters entered here //); 
} 
// Presumably, process the package here. 

你也許可以做到像這樣,只用自動分配,這絕對是最好的–最簡單,最安全,最有效的–當’小號適用:

void process(Package const& package) 
{ 
    // Process the package here. 
} 

void foo() 
{ 
    // ... whatever, then: 

    switch(shippingOption) 
    { 
    case overnight: 
     process(OvernightPackage(blah)); 
     break; 
    case twoDay: 
     process(TwoDayPackage(blah)); 
     break; 
    default: 
     assert(false); // Should never get here. 
    } 
} 

如果這是不可能的,那麼你可以使用包對象的動態分配。問題是,作爲初學者,你可能不知道評估上述內容是否實際上是不可能的(儘管可以很容易地看出它的確是可能的)。總之,動態分配使用智能指針,如C++ 11 std::shared_ptr

typedef std::shared_ptr<Package> PackagePtr; 

PackagePtr foo(blah, blah, arguments) 
{ 
    // ... whatever, then: 

    switch(shippingOption) 
    { 
    case overnight: 
     return PackagePtr(new OvernightPackage(blah)); 
    case twoDay: 
     return PackagePtr(new TwoDayPackage(blah)); 
    default: 
     assert(false); // Should never get here. 
    } 
} 

當你獲得更多的經驗,你應該努力始終使用可用,可以做的工作最受限的智能指針,這可能是例如std::unique_ptr。因爲將所有權轉讓給共享智能指針很容易,但很難將其轉移回所有權指針。然而,作爲初學者,你會發現std::shared_ptr對大多數事物都很好,在這方面它就像一個馬鈴薯。 ;-)