请教高手......一个简单的包装类问题,头痛ing
我现在有一个Template的二元树class,而且只允许使用一个实例,却被要向里面插入2个不同的Class,我还不能改动二元树class的代码。
二元树一旦实例化了就只能接受实例化的Class了,要向里面插入2个Class我唯一想到的办法就是写一个包装类。
包装类的生明(file_system.hpp)是这样的:
enum eContain_type{ None, eFile, eDirectory };
class Container {
public:
Container(){} //default constructor
~Container() {} //destructor
Init(eContain_type eType); //init. function
private:
void *Element; // 我想用这个变量动态指向File或Directory类,可是不知道怎么写
};
包装类(file_system.cpp)的实现代码:
Container::Init(eContain_type eType){
File *tFile = new File;
Directory *tDirectory = new Directory;
switch(eType){
case eFile:
{Element = tFile;}
break;
case eDirectory:
{Element = tDirectory;}
break;
case None:
break;
default:
;
}
}
我的Main.cpp里这样写的:
int main(){
Container CC;
CC.Init(eFile);
CC.Element->GetFileDirGroup(); // GetFileDirGroup()是class File里的一个方法
return 1;
}
编译时报错
error C2227: left of '->GetFileDirGroup' must point to class/struct/union
error C2248: 'Element' : cannot access private member declared in class 'Container'
file_system.hpp(24) : see declaration of 'Element'
======
我的File和Directory都是普通的非Template类。
我不能用模板来做,因为模板最后使用时要实例化,两个类就是两种实例化的包装类实例。我不允许使用第二个二元树的实例,所以无法在同一个二元树实例里实现插入两个实例化的包装类。
我研究过空指针,可是不得要领。我想要是有可以根据输入动态指向不同实例的聪明指针就好了。
各位高手能给我点建议吗?
谢谢了!!!
(3天内结贴,保证全分奉送)
问题点数:100、回复次数:11Top
1 楼vivalite_wei()回复于 2004-12-04 09:03:18 得分 0
对了,刚才我忘了说了,那个File和Directory类都是已实现的类,我也动不得。
所以现在夹在已实现的类之间要做转换,很难受Top
2 楼dot99(又来混CSDN来了)回复于 2004-12-04 11:49:31 得分 60
CC.Element->GetFileDirGroup(); // GetFileDirGroup()是class File里的一个方法
....
你的Element是个private,你怎么。。。。
暂时看到这个。。。。
Top
3 楼dot99(又来混CSDN来了)回复于 2004-12-04 12:04:13 得分 0
>>我研究过空指针,可是不得要领。我想要是有可以根据输入动态指向不同实例的聪明指针就好了。
什么是空指针,你是指void吗?
在这个思路上,你可以写个
struct elem_st{
void * point_to_inst;
inst_category cate;
};
pti用来指向你的instance
cate用来标识
container提供相应的select(根据cate),在运行时候进行cast
这样能满足你的要求
不过,这个有点。。。。。丑陋
而且还得注意该死的内存相关问题
其他方向上嘛~~~
提供个思路
多态,使用这个东东
问一个,你是指二元树不能修改,还是指插入的class不能修改
对于插入的class能修改:
给他们提供一个基类,其他的,慢慢解决吧~~
主要是时间不够咯。。。。。。。。老大逼吃饭~~
等下来继续回
Top
4 楼vivalite_wei()回复于 2004-12-04 12:37:41 得分 0
太感谢楼上了,我想过多态,可是我这个问题是二元树和插入的Class都不能修改,所以,唉......
您说的第一个方法我有点不太明白,能给小弟详细解一下吗,非常感谢!Top
5 楼imRainman(雨人)回复于 2004-12-04 13:07:06 得分 40
#include <algorithm>
#include <typeinfo>
#include <exception>
#include <iostream>
#include <vector>
using namespace std ;
class CAnyType
{
protected :
class CObject
{
public :
virtual CObject* Clone( ) = 0 ;
virtual const std::type_info& Type( ) const = 0 ;
virtual const std::type_info& PointerType( ) const = 0 ;
} *m_pObject ;
template <typename TypeName>
class CTheObject : public CObject
{
public :
TypeName m_tElement ;
public :
CTheObject(const TypeName &object) :
m_tElement(object) { }
virtual CObject *Clone( )
{
return new CTheObject<TypeName>(m_tElement) ;
}
virtual const std::type_info& Type( ) const
{
return typeid(TypeName) ;
}
virtual const std::type_info& PointerType( ) const
{
return typeid(TypeName*) ;
}
} ;
public :
CAnyType( ) :
m_pObject(0) { }
template <typename TypeName>
CAnyType(const TypeName& object) :
m_pObject(new CTheObject<TypeName>(object)) { }
CAnyType(const CAnyType& other) :
m_pObject(other.m_pObject ? other.m_pObject->Clone( ) : 0) { }
template <typename TypeName>
TypeName &as( )
{
#ifdef _DEBUG
if (m_pObject->Type( ) != typeid(TypeName)) throw std::exception("bad cast") ;
#endif
return static_cast<CTheObject<TypeName> *>(m_pObject)->m_tElement ;
}
template <typename TypeName>
TypeName &as( ) const
{
#ifdef _DEBUG
if (m_pObject->Type( ) != typeid(TypeName)) throw std::exception("bad cast") ;
#endif
return static_cast<CTheObject<TypeName> *>(m_pObject)->m_tElement ;
}
void Swap(CAnyType& rhs)
{
std::swap(m_pObject, rhs.m_pObject) ;
}
CAnyType &operator =(const CAnyType& rhs)
{
Swap(CAnyType(rhs)) ;
return *this ;
}
template <typename TypeName>
CAnyType &operator =(const TypeName& rhs)
{
Swap(CAnyType(rhs)) ;
return *this ;
}
const std::type_info& Type( ) const
{
return m_pObject ? m_pObject->Type( ) : typeid(void) ;
}
const std::type_info& PointerType( ) const
{
return m_pObject ? m_pObject->PointerType( ) : typeid(void) ;
}
public :
~CAnyType( )
{
delete m_pObject ;
}
} ;
class CFile
{
public :
void GetFileDirGroup( ) { cout << "CFile\n" ; }
} ;
class CDirectary
{
public :
void GetxxxxxxxGroup( ) { cout << "CDirectary\n" ; }
} ;
void main( )
{
vector<CAnyType> v ;
v.push_back(CFile( )) ;
v.push_back(CDirectary( )) ;
v[0].as<CFile>( ).GetFileDirGroup( ) ;
v[1].as<CDirectary>( ).GetxxxxxxxGroup( ) ;
}
Top
6 楼imRainman(雨人)回复于 2004-12-04 13:08:25 得分 0
最好在vc7.0以上编译。6.0上好像会有点儿语法的问题~Top
7 楼dot99(又来混CSDN来了)回复于 2004-12-04 13:24:51 得分 0
struct classA_tag{};
struct classB_tag{};
class holder {
public:
enum ID_T { ID_classA, ID_classB };
void setObj(classA* p)
{
holder_ = static_cast<void*>(p);
id_ = ID_classA;
}
void setObj(classB* p); // the same
void* getObj()
{
return holder_;
}
classA* getObj(classA_tag)
{
return id_ == ID_classA ? static_cast<classA*>(holder_) : 0;
}
classB* getObj(classB_tag); //the same
int getObjType() { return id_; }
private:
void * holder_;
ID_T id_;
};
这没办法在编译期就决断,为了减轻一点使用上的负担
只有这样
holder hobj;
classA *pobjA = new classA();
hobj.setObj(pobjA);
//....
classA *pa = 0;
if ( (pa = hobj.getObj(classA_tag())) != 0 ) {
pa->.....;
};
暂时只有这样了....
同样,如果要判断一个holder的类型
switch (hobj.getObjType())
{
case holder::classA_ID:
pa = hobj.getObj(classA_tag());
break;
//....
//或者自己来
case holder::classB_ID:
pb = static_cast<classB*>(hobj.getObj());
break;
};
Top
8 楼dot99(又来混CSDN来了)回复于 2004-12-04 13:32:25 得分 0
imRainman 的办法不错~~~:D
或者,干脆点~~~
有轮子了~~我们使用
boost::anyTop
9 楼dot99(又来混CSDN来了)回复于 2004-12-04 13:35:16 得分 0
楼主~~~也可以把我那个东东用template扩展成rainman的那个样子~~~
嘿嘿~
自己来咯
不过,我还是推荐boost::any
Top
10 楼imRainman(雨人)回复于 2004-12-04 14:13:42 得分 0
呵呵,boost::any就不用啦,
我那个CAnyType就是个boost::any的盗版 :@)Top
11 楼vivalite_wei()回复于 2004-12-04 14:42:02 得分 0
谢谢两位高人了!!!!Top




