现在的位置: 首页 > 综合 > 正文

C++与C#对比学习:多重继承

2013年09月09日 ⁄ 综合 ⁄ 共 2217字 ⁄ 字号 评论关闭

   我们知道C++中类可以多重继承,这也符合现实情况,比如某个绿帽高戴的男同志身边的某位美女可能同时具备几个身份,老婆,小三,孩子他妈.这样的话这位美女得同时继承这三个类.不过由于多继承会有一些缺陷,比如二义性.而且虽然多继承方便直观点,但没有它也不是不行.其实少了类少了面向对象也不是就做不了啥事,像C语言没有类还不是用的好好的.所以啊这个世界上很多事并不是那么必不可不少的.比如你明天光荣牺牲了这个世界还照样运转.

  由于考虑到多重继承的一些缺陷,C#中的类干脆直接不让用多继承.不过有个例外就是接口可以多继承.下面来说下接口的多继承

C#接口(interface)多重继承

假如有两个接口IWife,ILover

internal interface IWife

    {

        void DoIt();

        void  CleanHouse();

    }

internal interface ILover

    {

        void DoIt();

    }

然后有个类Girl,继承这两个接口

/*我们发现接口的修饰符是internal,但此时类的修饰符是public.如果不是继承接口还是继承某个internal的类会报错的.因为子类的访问权限不能大于父类.为啥继承接口会例外?

//可能觉得接口反正里面是空的,没啥可保护的.就不做这样的限制了吧.另外如果某个类是internal的,但其中的函数可以是public.然后即使函数访问权限大于类也没用.因为毕竟要通过类才能访问类中函数*/

public Girl: IWife,ILover 

{

    public  void DoIt()         //两个接口中都有此函数.继承时只要一个就搞定.

     {

       Console.Write("Do something happy and interesting");

      }          

    public void  CleanHouse()            //其中的public修饰符是必不可少的,不然会报错.

   {

      Console.Write("Clean house is boring");

   }

}     

 

接口中的同名函数

 这样使用是一点问题也没有.不过你可能看到上面的两个接口中有相同的函数DoIt,在继承下来后被当成一个函数去处理了.如果想分开单独处理咋整呢?

在上面的Girl中添加如下两个函数就OK

   void IWife.DoIt()                    //注意这两个函数能不能加任何修饰符,如果加public会出错

{

Console.Write("Do something with husband");

}

void ILover.DoIt()

{

Console.Write("Do something with a handsome boy");

}

 

加了这两个函数后我们会发现个有趣的问题.添加的这两个函数在类Girl中无法去用它.在类内部没法调用,在外部更不能.因为没有修饰符默认是private的.

那这样添加两个函数有啥用啊,怎么去用?可以这样用

Girl  beautifulGirl = new Girl();

((IWife)beautifulGirl).DoIt();        //结果是Do something with husband

((ILover)beautifulGirl).DoIt();      //结果是Do something with a handsome boy

beautifulGirlDoIt();      //结果是 Do something happy and interesting

背后的机制具体是怎样的不太清楚.不过从结果看下来这种情况下DoIt函数有点像虚函数了.在子类中通过带接口名做前缀重写后相当于实现了接口中对应的DoIt函数.但子类Girl中自己又另外重写了DoIt.

C++类多重继承

据说标准C++中是没有接口这概念,那这里就不说啥接口多重继承了,只说类的多重继承.用法其实跟上面的C#接口多重继承差不多.下面只讲下多重继承里容易犯错的地方.

class  Object

{

public:

void DoIt(){cout<<"Hit bad boy."<<endl;}

}

;

class AA :Object

{

};

class BB:Object

{

};

class Arwen:AA,BB

{

};

上面是个简单的例子.有一个父类Object,然后类AA,BB分别继承自它.最后有个类Arwen同时继承AA,BB.

像下面这样去调用,会报错:ambiguous access of "DoIt".

int _tmain(int argc, _TCHAR* argv[])

{

Arwen weiwen;

weiwen.DoIt();

return 0;

}

因为AA,BB中都同时继承了DoIt这函数,而Arwen继承了它们俩.然后调用DoIt时就不知道是调用从AA继承来的DoIt还是从BB继承来的DoIt就是就报错了.

那咋整啊.假如Object,AA,BB这些类都是类库提供的,我们不能改可咋整啊.

只能在类Arwen中重新写个DoIt函数了,比如

class Arwen:AA,BB

{

void DoIt(){cout<<"Oh,my god.Do it myself."<<endl;

};

这真的有点操蛋了啊,好好的想继承个函数来玩玩结果出错了.还得自己再写个.

抱歉!评论已关闭.