最近在程序時,遇到一種情況,以前也有遇到過,不過采用另外一種方法繞過了。具體問題如下:
const Layer& Frame::GetLayer(uint32 layerIndex) const
{
if(CheckLayerIndexValid(layerIndex))
{
return m_layers[layerIndex];
}
return ?; // what ? how ?
}
在這種情況下,我們可以改為返回指針:
const Layer* Frame::GetLayer(uint32 layerIndex) const
{
if(CheckLayerIndexValid(layerIndex))
{
return m_layers[layerIndex];
}
return 0;
}
或者作為參數返回:
bool Frame::GetLayer(uint32 layerIndex, Layer &layer) const
{
if(CheckLayerIndexValid(layerIndex))
{
layer = m_layers[layerIndex];
return true;
}
return false;
}
但如果我們想保持第一種函數形式,只是想返回對象的引用怎麼辦?
我想到空對象模式,當需要一個無意義的對象時,可以返回事先確定好的空對象,類似代碼如下:
#include <boost/shared_ptr.hpp>
template<class T>
class Nullable
{
protected:
Nullable(){ }
virtual ~Nullable(){ }
public:
static boost::shared_ptr<T>& NullPtr()
{
return ms_nullPtr;
}
bool IsNull()
{
return this == ms_null;
}
private:
static T* Null()
{
if(0 == ms_null)
{
ms_null = new T;
}
return ms_null;
}
private:
static T *ms_null;
static boost::shared_ptr<T> ms_nullPtr;
};
template<class T>
T* Nullable<T>::ms_null = 0;
template<class T>
boost::shared_ptr<T> Nullable<T>::ms_nullPtr(Nullable::Null());
class Layer : public Nullable<Layer>
{
public:
Layer(){ }
~Layer(){ }
public:
int m_id;
};
當在上述情況時,我們可以返回 *Layer::NullPtr(),但這樣就必須在獲得函數返回值後檢查是否IsNull()以確定該對象是否有意義,略顯麻煩。而且在返回空對象而非引用時,
IsNull()也不再有效。
我的例子舉得不是太合適,現在這個例子layerIndex確實應該有效,但如果:某個Manager存了一系列以id為鍵值的layer,需要根據id查找相應的layer,此時查不到也是正常的,此時不應該是錯誤或異常。