2012-04-03 78 views
3

我有這樣的事情:C++:引用和工廠

struct D { 
    virtual void operator() {...}; 
} 
struct D1 : public D { 
    virtual void operator() {...}; 
} 
struct D2 : public D { 
    virtual void operator() {...}; 
} 

void foo(D &d) {...}; 

所以這是好的,並很好地控制了我的D的生命週期:

foo(D()); 
foo(D1()); 
foo(D2()); 

但我選擇我的d變種在多個地方,所以我想要一個簡單的工廠:

const D& make_D() 
{ 
    // BAD, returning reference to temporary 
    if(is_tuesday()) 
     return D1(); 
    return D2(); 
} 

而是參考返回到一個臨時的,我可以返回一個OBJE ct,但隨後我切片到基類。或者,我可以從我的工廠返回一個指針,但客戶端必須刪除它。其他更復雜的解決方案也會給客戶帶來更多負擔。

有寫類似

D& d = make_D(); 
foo(d); 

(甚至foo(make_D()))的方法嗎?我們的目標是將各種D定義和make_D()中的複雜性都包含進來,以便諸如foo()之類的函數和那些調用這些函數的函數不必擔心。

+0

注意:'foo(D())'不會被編譯(不在符合的編譯器下,甚至VS會發出關於非標準行爲的警告),因爲臨時的不能綁定到非const的l值引用。 – 2012-04-03 10:20:47

回答

5

通常的方法是返回一個指針或一個智能指針。

使用指針的缺點是讓用戶管理其內存。

如果你返回一個智能指針,這不再是一個問題。

const SmartPtr<D> make_D() 
{ 
    if(is_tuesday()) 
     return SmartPtr(new D1()); 
    return SmartPtr(new D2()); 
} 
5

不幸的是,這是不可能的。

通常情況下,我做的是使用std::unique_ptr(有時std::shared_ptr,當它是無法使用std::unique_ptr):

typedef std::unique_ptr<D> Dptr; 
Dptr make_D() 
{ 
    Dptr p(nulptr); 

    if(is_tuesday()) 
     p.reset(new D1); 
    else 
     p.reset(new D2); 

    return p; 
} 
0

首先,我不太肯定我明白了。您列出的代碼不是合法的 ,並且不會被編譯。你確定它是不是:

struct D 
{ 
    virtual void operator()() const { /* ... */ } 
}; 

和:

void foo(D const& d) { /* ... */ } 

調用,或者是可變的? (可能不會,因爲你沒有傳入任何 參數,並且在使用後丟棄該對象。)如果沒有,那麼你可以簡單地返回對靜態實例的引用。這是我使用的通常的 解決方案。否則,可以使用信封信封成語來使可複製對象 呈現多態,但它的工作位爲 ,並且具有顯着的運行時間開銷,因爲它通常要求 需要克隆每個副本的實際對象。