2012-08-08 72 views
1

我已經定義了一個成員變量,如下所示。由於變量不會被傳遞,所以我決定在這裏使用scoped_ptr而不是shared_ptr。推遲boost的初始化:: scoped_ptr

class ClassName 
{ 
public: 
    ClassName() 
    { 
     Initialize(); 
    } 

    virtual void Initialize() = 0; 

protected: 
    boost::scoped_ptr<int> m_scpInt; 
} 

class ClassNameB : public ClassName 
{ 
public: 
    virtual void Initialize() 
    { 
     m_scpInt.reset(new int(100)); 
    } 
} 

由於scoped_ptr的極限,如果我決定推遲變量的初始化在以後的時間,我得到的唯一的選擇是調用復位。

Q1>這是一個很好的做法嗎?

Q2>否則,是否有更好的解決方案?

謝謝

///更新-1 ///

這是我真正想做的事情。

我想強制每個派生類定義一個名爲Initialize的函數,然後調用函數InitializeVarA和InitializeVarB。如您所示,我們不能在構造函數中調用虛函數。

class ClassName 
{ 
public: 
    ClassName() 
    { 
    }  
    virtual void Initialize() 
     { 
      InitializeVarA(); 
      InitializeVarB(); 
     }   
    protected: 
     virtual void InitializeVarA() {} 
     virtual void InitializeVarB() {} 
} 

class ClassNameB : public ClassName 
{ 
public: 
    ClassNameB() 
    { 
    }  
    virtual void Initialize() 
     { 
      InitializeVarA(); 
      InitializeVarB(); 
     }   
    protected: 
     virtual void InitializeVarA() {} 
     virtual void InitializeVarB() {} 
} 

ClassNameB cb; 
cb.Initialize(); 

我有比這更好的解決方案嗎?

+2

好像'scoped_ptr'是不是真的適合你的正確的事在這種情況下使用。 'std :: unique_ptr'有什麼問題? – 2012-08-08 14:50:31

回答

4

這是一個很好的做法嗎?

使用reset來重置範圍指針是好的。

嘗試通過從基類的構造函數調用虛函數來初始化派生類不僅是不好的做法;這是不對的。此時,對象的動態類型是基類,並且該函數是純虛擬的,因此調用它會導致未定義的行爲。

即使您將其設爲非純文本,您仍然無法在該位置調用派生類的覆蓋,因此指針將不會被重置。

否則,有沒有更好的解決方案?

你可以在派生類的構造函數,這是基類的後立即調用做到這一點:

class Base { 
public: 
    Base() { /* don't call any virtual functions here */ } 

protected: 
    boost::scoped_ptr<int> p; 
}; 

class Derived : public Base { 
public: 
    Derived() { 
     p.reset(new int(100)); 
    } 
}; 

或者你也可以通過分配的內存基類的構造函數和初始化從指針。這有點危險 - 你必須確保在任何可能拋出異常的內容之前立即初始化指針,否則內存可能會泄漏。

class Base { 
public: 
    Base(int * p) : p(p) {} 

private: // doesn't need to be protected now 
     // (unless something else in the derived class needs access) 
    boost::scoped_ptr<int> p; 
}; 

class Derived : public Base { 
public: 
    Derived() : Base(new int(100)) {} 
}; 

在C++ 11,你可以使用unique_ptr,這是可移動的,以避免泄漏的風險:

class Base { 
public: 
    typedef std::unique_ptr<int> ptr; 
    Base(ptr && p) : p(p) {} 

private: 
    ptr p; 
}; 

class Derived : public Base { 
public: 
    Derived() : Base(ptr(new int(100))) {} 
}; 
+0

首先感謝您指出「在施工過程中不要調用虛擬功能」。請參閱我更新的帖子。謝謝 – q0987 2012-08-08 15:17:43