根據子類類型訪問其特有操作
描述:一個常見遇到的解決方案,下面記錄下來。
1個功能模塊,有一個簡單的繼承體系,基類假設為Base.
然后通過一個接口,如何訪問子類的特有操作?
/// 外部提供一個下面接口:
virutal Base* getBase() const ;
///我們得到Base指針后,需要根據Base的類型進行特定的操作,
void function(Base *obj)

{
/**//// 由于obj只是Base基類指針
BaseObj1 * obj1;
BaseObj2 * obj2;
if ( obj1 = dynamic_cast<BaseObj1*>( obj ) )
{
/**//// to do
}
else if ( obj2 = dynamic_cast<BaseObj2*>( obj ) )
{
/**//// to do
}
else 
{
/**////
you get the idea
}
}BaseObj1 和 BaseObj2 都繼承與Base基類,隨著繼承體系的擴大,那么if else條件判斷會長,是否有更高效的方式
解決方式:
1.多態:常見而且簡單的方式
針對上面描述的問題,首先想到的是多態,基類寫一個虛函數,每個之類重寫此接口。
void function( Base *obj )

{
obj->todo();
}
1)但是如果function函數的某個操作是free obj時,通過todo恐怕不合適。
2)可能有些子類型不關心不必要的接口但是也得寫。
3)如果todo包含多個操作,則會讓之類變得很龐大。
2. visitor模式.
那么同時得提供下面的操作接口:
void visit(const BaseObj1& obj1 );
void visit(const BaseObj2& obj2 );

/**//// 如果有多個子類型的話,需要重寫visit,此時fuction
void function( Base *obj )
{
visit( obj );
}
1)同樣多少Base子類得些多少 visit接口。
2)還得倚靠多態類型轉換調用特定的visit接口,因為obj還是Base* 類型,還得轉換具體的類型。
3.把所有操作綁定到類身上:
1)定義針對每個Base子類操縱接口類
2)Base所有子類型的保存需要操縱對象.
Base類定義:
template < typename type>
class Base

{
public:
class Handle
{
public:
Handle()
{
Base<type>::m_handlelist.push_back( this );
}
virtual void todo( const type& tp) = 0;
};
public:
static void todo(Base<type> * base)
{
for( std::list<Handle*>::iterator itr = m_handlelist.begin() ;
itr != m_handlelist.end() ; itr ++ )
{
/**//// 通過模板轉換為制定具體類型,然后根據具體參數調用具體的接口
(*itr)->todo( *(type*)base );
}
}
void todo()
{
type::todo( this );
}
protected:
typedef std::list<Handle*> listtype;
static listtype m_handlelist;/**//// 聲明為靜態,所以當模板實例化的時候,會根據不同的類型存在多份數據。
};
定義2子類:
class BaseObj1 : public Base< BaseObj1 >

{
/**///// 定義接口
}
class BaseObj1 : public Base< BaseObj1 >

{
/**//// 定義接口
}

定義操作類型:
class DoHandle : public BaseObj1::Handle ,
public BaseObj2::Handle 

{
public:
virtual void todo(const BaseObj1 & obj1)
{
std::cout <<" baseobj1 m_type address " << std::endl;
/**//// obj1.print();
}
virtual void todo(const BaseObj2 & obj2)
{
std::cout <<" baseobj2 m_type address " << std::endl;
/**//// obj2.print();
}
};
現在function接口變為下面了
template<typename type>
void function( Base<type> * base)

{
base->todo();
}
調用方式:
BaseObj1 obj1;
BaseObj2 obj2;
DoHandle handle; /**////綁定到obj1,obj2對象的m_handlelist列表中。
fun( & obj1 );
fun( & obj2 );
最后發現最后一個有點像Listener模式,-_-|||
總結完畢:
代碼:
/Files/expter/test.rar
posted on 2011-02-24 23:23 expter 閱讀(2267) 評論(4) 編輯 收藏 引用 所屬分類: 其他學習筆記 、工作筆記 、生活筆記 、算法與數據結構

