2010-07-07 114 views
0

我有一個基類(Base),其構造函數的參考作爲參數。在我的派生類的構造函數中,我調用超類的構造函數,當然我需要傳遞一個引用作爲參數。但我必須獲得其中的返回類型是值的方法這樣的說法......C++:引用作爲構造函數參數,幫助

我會給出一個簡單的例子:

class Base 
{ 
public: 
    Base(MyType &obj) { /* do something with the obj */} 
}; 

class Derived : public Base 
{ 
public: 
    Derived(MyOtherType *otherType) : 
     Base(otherType->getMyTypeObj()) // <--- Here is the error because (see *) 
    { 
     // * 
     // getMyTypeObj() returns a value and 
     // the Base constructor wants a reference... 
    } 
}; 

class MyOtherType 
{ 
public: 
    MyType getMyTypeObj() 
    { 
     MyType obj; 
     obj.setData(/* blah, blah, blah... Some data */); 
     return obj; // Return by value to avoid the returned reference goes out of scope. 
    } 
}; 

我怎樣才能解決這個問題?

+0

基礎構造函數是否修改對象,對其進行引用?有什麼限制?我的意思是,代碼中的哪些部分可以修改,哪些部分必須保持不變? – 2010-07-07 16:05:07

+2

使參數成爲常量引用。 – 2010-07-07 16:06:24

+0

const引用如何提供幫助?它仍然是一個不再存在的東西的參考。 – 2010-07-07 16:31:36

回答

3

更改基類: class Base { public: Base(const MyType &obj) { /* do something with the obj */} };

更新:如果要修改的obj你不能明顯地有const參考。在這種情況下,您可以:

1)按值傳遞參數。這將會產生副本的開銷,但是避免以後必須明確釋放它。

2)更改MyOtherType::getMyTypeObj()

MyType& MyOtherType::getMyTypeObj() 
{ 
    MyType* obj = new MyType(); 
    obj->setData(/* blah, blah, blah... Some data */); 
    return *obj; 

}

在這種情況下,要記住刪除對象,你用它做了。

+2

這將工作,除非'/ *做obj * /'意味着他想修改obj。 – 5ound 2010-07-07 16:27:58

+0

當然,這是超載派上用場的地方:) – Cogwheel 2010-07-07 16:47:25

+0

當然。但是,如果他想修改對象,他可能會更好地製作自己的副本。更新了我的答案。謝謝 – 341008 2010-07-07 17:20:24

0

該問題是由GetMyTypeObj()返回基於堆棧的'obj'副本引起的,因此編譯器在構造函數中創建了一個臨時變量,其範圍僅僅是Base()構造函數。

1

認真嗎?你的問題有答案。將參數的類型更改爲Base構造函數,或者更改getMyTypeObj()的返回值的類型,以使這些類型兼容。

+0

+1:它好像是你的所有代碼,那麼爲什麼解決方法可以解決一個問題? – rubenvb 2010-07-07 17:05:24

0

在我看來,有兩種方法可以解決這個問題。

  1. 更改Base構造函數以通過值而不是通過引用接受MyType對象。這將複製臨時對象並解決範圍問題。

  2. 或者,您可以在Derived中創建一個MyType對象的副本並傳遞對該對象的引用。

class Derived : public Base 
{ 
public: 
    Derived(MyOtherType *otherType) : 
     Base(m_myType) , 
     m_myType(otherType->getMyTypeObj()) 
    { 
     // ... 
    } 
private: 
    MyType m_myType; 
}; 

選項1是簡單,我一般會推薦它。
選項2是爲了防止其他約束條件阻止您更改基礎構造函數,