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;

 

©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页