2015-03-19 87 views
1

我有一個模板包裝器,其中包含繼承純虛擬類的類的實例。
我的問題是如何將數據存儲在包裝中。
- 我無法使用副本,因爲純虛擬類不能實例化(或者如果我使用簡單的虛擬類,則會切片)。
- 我沒有設法保留參考。這個參數變得無效,因爲我不管理我得到的對象的分配(超出範圍)。
- 我唯一的解決方案是使用指針,即使我想避免這種情況,因爲這不是很安全,我需要我的代碼才能健壯。
我該怎麼辦?C++存儲對作爲類成員的純虛擬類的引用

下面是模擬我的問題一個小例子:

#include <iostream> 
#include <string> 
#include <ctime> 
#include <cmath> 

using namespace std; 

class Module 
{ 
public: 
    Module() : m(rand()) 
    { 
     cout << "m = " << m << endl; 
    } 

    virtual void f() = 0; 

    int m; 
}; 

class ModuleA : public Module 
{ 
public: 
    ModuleA() : ma(rand()) 
    { 
     cout << "ma = " << ma << endl; 
    } 

    void f() {} 

    int ma; 
}; 

template<typename T> 
class Container 
{ 
public: 
    Container(T e) : element(e) {} 

    T element; 
}; 

// Objects are created outside of main 
ModuleA createModule() 
{ 
    return ModuleA(); 
} 

Container<Module&> createContainer() 
{ 
    return Container<Module&>(createModule()); 
} 

int main() 
{ 
    srand((unsigned int)time(NULL)); 

    Container<Module&> conta = createContainer(); 

    ModuleA& ca1 = dynamic_cast<ModuleA&>(conta.element); // wrong ! 

    system("pause"); 

    return 0; 
} 
+0

這不應該編譯。您將非常量引用綁定到臨時對象。 – 2015-03-19 11:24:17

+0

此代碼在Visual Studio 2013中編譯時沒有任何警告。 – 2015-03-19 11:24:56

+0

@AntoineLafarge然後你使用的是非標準的擴展(它們可能在編譯器中默認啓用)。你應該在問題中說明編譯器。 – user2079303 2015-03-19 11:29:08

回答

2

您可以使用您的容器std::shared_ptr,即

template<typename T> 
class Container 
{ 
public: 
    // The pointer you get must be managed as well 
    Container(std::shared_ptr<T> e) : element(e) {} 

    std::shared_ptr<T> element; 
}; 

,這將是絕對安全的。事實上,如果對象在創建它的代碼中超出範圍,那麼在容器超出範圍之前,您仍然有一個有效的指針。如果std::shared_ptr的語義不符合您的情況,您可以稍微調整內存所有權關係std::weak_ptrstd::unique_ptr

你一定要看看std::weak_ptr,因爲它可以讓你禁止了一些代碼,以指針的所有權,但仍允許訪問如果指針在您需要訪問它的位置有效。它還可以防止內存保留週期,因爲std::weak_ptr不擁有內存。

+1

爲什麼不使用'unique_ptr'並返回一個引用? – 2015-03-19 11:31:05

+2

@GiulioFranco OP表示:「這個參數變得無效,因爲我沒有管理我得到的對象的分配(超出範圍)。」所以我相當認爲包裝不應該是唯一的所有者。如果容器超出範圍,那麼這種情況就不會很好,但是對象仍然通過例如其他地方被引用。一個原始指針。 – JBL 2015-03-19 11:34:27

+2

我會使元素爲private,並創建一個返回weak_ptr的公共成員函數。我不會返回unique_ptr的原始指針。 – Robinson 2015-03-19 11:39:11