0
点赞
收藏
分享

微信扫一扫

C++多继承 基类命名冲突


多继承中的二义性问题

        在派生类中对基类成员的访问应该是唯一的。但是,在多继承情况下,可能造成对基类中某个成员的访问出现了不唯一的情况,这时就称对基类成员的访问产生了二义性。

class base1
{
public:
void fun();
};
class base2
{
public:
void fun();
};
class derived:public base1,public base2{};
int main()
{
derived obj;
obj.fun(); //产生二义性
return 0;
}

      当派生类derived的对象obj访问fun( )函数时,由于无法确定访问的是基类base1中的fun()函数,还是base2中的,因此对fun()函数的访问将产生二义性。

       解决这个问题的两种方法:

           (1)通过作用域运算符(::)明确指出访问的是基类base1的fun()函数,还是基类base2的fun()函数。

                         例:  obj.base1::fun();

                使用作用域运算符进行限定的一般格式:

                        <对象名>.<基类名>::<成员名>   //数据成员      <对象名>.<基类名>::<成员名>(<参数表>)   //成员函数

           (2)在类中定义同名成员。例:


 


class derived
{
public:
void fun(){base1::fun();} //注意两种表示方法的区别
//或 base1::fun;
};

下面介绍一下ATL风格的解决方案:

//ATL风格
template< typename TDerive >
class CAdaptBaseA : public CBaseA
{
public:
virtual void Init()
{
TDerive *pThis = static_cast<TDerive*>( this );
pThis->BaseAInit();
}
};

template< typename TDerive >
class CAdaptBaseB : public CBaseB
{
public:
virtual void Init()
{
TDerive *pThis = static_cast<TDerive*>( this );
pThis->BaseBInit();
}
};

class CDeriveATLStyle : public CAdaptBaseA<CDeriveATLStyle>, public CAdaptBaseB<CDeriveATLStyle>
{
public:
void BaseAInit()
{
AfxMessageBox( _T("BaseAInit") );
}
void BaseBInit()
{
AfxMessageBox( _T("BaseBInit") );
}
};

这种实现真用了继承,而没有模拟。不过在继承中增加了一个中间层,CAdaptBaseA和CAdaptBaseB,这两个类是模板类,分别继承自CBaseA和CBaseB,模板参数是即将从它们派生的子类。这种模板是典型的ATL风格的模板,十分精妙。中间适配类CAdaptBaseA的Init实现中有一行代码:

TDerive  *pThis = static_cast<TDerive*>( this );

这段代码,我初学ATL的时候也是看了好多遍才看懂,不过既然看懂了也就爱上这种风格了,同MFC风格的实现一样,获得子类实例pThis后,就直接调用子类中针对CBaseA::Init的实现BaseAInit成员方法了。

CDeriveATLStyle *pDerive = new CDeriveATLStyle;

CBaseA *pBaseA = dynamic_cast<CBaseA*>(pDerive);
pBaseA->Init();

CBaseB *pBaseB = dynamic_cast<CBaseB*>(pDerive);
pBaseB->Init();

delete pDerive;

 

举报

相关推荐

0 条评论