posts - 195,  comments - 30,  trackbacks - 0

http://hi.baidu.com/knowtohow/blog/item/520a5e3e2808753e70cf6c46.html

关于C#,C++,Java在继承,覆盖和多态,抽象类等几个方面的比较归纳。
C#,C++用visual studio2005编译通过;java代码用JDK1.4.2编译通过。


一、继承中的带参数构造函数
=============================
C#示例:
//myClass.cs

using System;
using System.Collections.Generic;
using System.Text;

namespace myClass
    class myFirst{
        int value_myFirst;
        public myFirst(int f)
        {
            value_myFirst = f;   
        }
    }
    
    class mySecond : myFirst{
        int value_mySecond;
        
        //构造函数传递参数时,采用base关键字,s在base()中不需重新声明类型int
        public mySecond(int s)
            : base(s)   
        {
            value_mySecond = s;       
        }
    }
        
    class Program
    {
        static void Main(string[] args)
        {
           
        }
    }
}


============================

C++示例:
#i nclude "stdafx.h"

class myFirst{
private:
    int value_myFirst;
public:
    myFirst(int f){
        value_myFirst = f;   
    }
};

//继承需要声明继承的方式,此处是public
class mySecond : public myFirst{ 
private:
    int value_mySecond;
public:
    //构造函数传递参数时,用基类类名,s基类类名()中不需声明类型int
    mySecond(int s) : myFirst(s){ 
        value_mySecond = s;       
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
return 0;
}

=============================

java示例:
package com;

class myFirst{
    int value_myFirst;
    public myFirst(int f){
        value_myFirst = f;   
    }
}

//继承采用extends关键字
class mySecond extends myFirst{
    int value_mySecond;
    public mySecond(int s){
        //传递给基类构造函数时,采用super关键字,而且必须是第一条语句。
        super(s); 
        value_mySecond = s;               
    }
}

public class myCon{
    public static void main(String[] args){
        
    }
}

注意:
1.注释中给出了三者的不同点。
2.另外,C++语法中定义的类后面必须加上分号";"
3.访问控制权限public等的格式,C#和java比较类似,C++相差很大。

二、方法覆盖与多态

C#示例:
//myClass.cs

using System;
using System.Collections.Generic;
using System.Text;

namespace myClass
{
    class myFirst
    {
        int value_myFirst;
        public myFirst(int f)
        {
            value_myFirst = f;
        }
        public void f1()
        {
            System.Console.WriteLine("myFirst.f1()!");
        }
        public virtual void f2() //virtual也可以提到最前面
        {
            System.Console.WriteLine("myFirst.f2()!");
        }
    }

    class mySecond : myFirst
    {
        int value_mySecond;

        public mySecond(int s)
            : base(s)
        {
            value_mySecond = s;
        }
        
        //使用关键字new覆盖基类中的同名方法
        public new void f1()     //new也可以提到最前面
        {
            System.Console.WriteLine("mySeconde.f1()!");
        }
        
        //error当基类函数myFirst.f1()没有声明为virtual,abstract时不能override!
        //public override void f1() 
        //{
        //    System.Console.WriteLine("mySeconde.f1()!");
        //}
        
        //基类函数中虽然声明是virtual,但是仍然可以用new覆盖。
        //public new void f2()
        //{
        //    System.Console.WriteLine("mySeconde.f2()!");
        //}
        
        ////基类函数中虽然声明是virtual,用override覆盖。
        public override void f2()   //override也可以提到最前面
        {
            System.Console.WriteLine("mySeconde.f2()!");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            myFirst mf = new myFirst(1);
            mySecond ms = new mySecond(2);
            mf.f1(); //myFirst.f1()!
            mf.f2(); //myFirst.f2()!
            ms.f1(); //mySeconde.f1()!
            ms.f2(); //mySeconde.f2()!

            mf = ms; //向上转型之后
            mf.f1(); //myFirst.f1()!
            
            //mySeconde.f2()! 这是用override的运行结果;
            //如果是new那么,结果是myFirst.f2()!
            mf.f2(); 
        }
    }
}

=============================

C++示例

#i nclude "stdafx.h"
#i nclude <iostream>
using namespace std;

class myFirst{
private:
    int value_myFirst;
public:
    myFirst(int f){
        value_myFirst = f;   
    }

void f1(){
cout<<"myFirst.f1()!"<<endl;
}
vitual void f2(){ //声明为虚函数
cout<<"myFirst.f2()!"<<endl;
}
};

class mySecond : public myFirst{
private:
    int value_mySecond;
public:
    mySecond(int s) : myFirst(s){
        value_mySecond = s;       
    }
    
    //直接覆盖基类函数,无需C#中的new
void f1(){
cout<<"mySecond.f1()!"<<endl;
}
    
    //覆盖基类需函数
void f2(){
cout<<"mySecond.f2()!"<<endl;
}
};

int _tmain(int argc, _TCHAR* argv[])
{
myFirst *mf = new myFirst(1);
mySecond *ms = new mySecond(1);
mf->f1(); //myFirst.f1()!
mf->f2(); //myFirst.f2()!

ms->f1(); //mySecond.f1()! 
ms->f2(); //mySecond.f2()!

mf = ms; //向上转型
mf->f1(); //myFirst.f1()!
mf->f2(); //mySecond.f2()!

myFirst mf1(1); //也可以
mf1.f1();

return 0;
}

=============================

java示例
//myCon.java

package com;

class myFirst{
    int value_myFirst;
    public myFirst(int f){
        value_myFirst = f;   
    }
    public void f1(){
        System.out.println("myFirst.f1()!");    
    }       
}


class mySecond extends myFirst{
    int value_mySecond;
    public mySecond(int s){        
        super(s); 
        value_mySecond = s;               
    }
    public void f1(){
        System.out.println("mySecond.f1()!");    
    }    
}

class myThird extends myFirst{
    int value_myThird;
    public myThird(int t){        
        super(t); 
        value_myThird = t;               
    }
    public void f1(){
        System.out.println("myThird.f1()!");    
    }     
}

public class myCon{
    public static void main(String[] args){
        myFirst mf = new myFirst(1);
        mySecond ms = new mySecond(1);
        myThird mt = new myThird(1);
                
        mf.f1(); //myFirst.f1()!             
        ms.f1(); //mySecond.f1()!      
        mt.f1(); //myThird.f1()!      
        
        //向上转型,由于java的动态绑定机制,
        //使得java能够调用派生类mySecond的f1()       
        mf = ms; 
        mf.f1(); //mySecond.f1()!
        
        mf = mt;
        mf.f1(); //myThird.f1()!      
               
    }
}

为了实现多态:
1.C#基类方法要声明为virtual,派生类覆盖时要用override;
2.C++基类方法要声明为virtual,派生类方法直接覆盖;
3.java直接覆盖就可以实现多态。

三、抽象类

C#示例
上面已经说明,虽然基类方法声明为virtual,以便派生类用override覆盖,但是派生类仍然可以用
new关键字覆盖(不具有多态性)。
可以强制让派生类覆盖基类的方法,将基类方法声明为抽象的,采用abstract关键字。
抽象方法没有方法体,由派生类来提供。

如果派生类不实现基类的抽象方法,则派生类也需要声明为abstract类

//myClass.cs

using System;
using System.Collections.Generic;
using System.Text;

namespace myClass{
    
    //类中只要存在抽象方法,就必须声明为抽象类
    abstract class myFirst 
    {
        int value_myFirst;
        public myFirst(int f)
        {
            value_myFirst = f;
        }
        
        //抽象方法没有方法体,以分号结尾。
        public abstract void f1();
        
        public void f2()
        {
            System.Console.WriteLine("myFirst.f2()!");
        }

        public virtual void f3()
        {
            System.Console.WriteLine("myFirst.f3()!");
        }
    }

    class mySecond : myFirst
    {
        int value_mySecond;

        public mySecond(int s)
            : base(s)
        {
            value_mySecond = s;
        }
        
        //覆盖基类抽象方法
        public override void f1()   
        {
            System.Console.WriteLine("mySeconde.f1()!");
        } 
         
        //覆盖基类一般方法     
        public new void f2()
        {
            System.Console.WriteLine("mySeconde.f2()!");
        }

        //覆盖基类虚拟方法
        public override void f3()
        {
            System.Console.WriteLine("mySecond.f3()!");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            //抽象类和接口不能声明对象
            //myFirst mf = new myFirst(1); 
            mySecond ms = new mySecond(2);
            
            ms.f1(); //mySeconde.f1()!
            ms.f2(); //mySeconde.f2()!
            ms.f3(); //mySecond.f3()!

            //这里向上转型采用强类型转换的方式
            ((myFirst)ms).f1();   //mySeconde.f1()! 
            ((myFirst)ms).f2();   //myFirst.f2()!
            ((myFirst)ms).f3();   //mySecond.f3()!
            
        }
    }
}

=============================

C++示例

纯虚函数是在基类中只宣布某个虚函数的原型,并且为了明确通知编译系统,
该虚函数在基类中不再定义具体操作代码,而在函数原型结束分号的左侧写
"=0"标识。这个不包含任何代码的虚函数被成为纯虚函数。

抽象类是含有纯虚函数的类,这种类不能声明任何对象,其作用就是为它的
派生类提供一种规定输入数据和返回类型接口的模板。

从抽象类派生的派生类,必须对基类的纯虚函数进行覆盖;否则编译系统将
报错。

基类中虚函数被派生类覆盖,则派生类对象调用的是派生类中重新定义的函
数代码。
基类中虚函数没有被派生类覆盖,则派生类对象调用的是基类中定义的函数
代码。
基类的纯虚函数在其派生类中必须被覆盖。

#i nclude "stdafx.h"
#i nclude <iostream>
using namespace std;

class myFirst{   //抽象类
private:
    int value_myFirst;
public:
    myFirst(int f){
        value_myFirst = f;   
    }

void f1(){            //一般函数
cout<<"myFirst.f1()!"<<endl;
}
virtual void f2(){   //虚函数
cout<<"myFirst.f2()!"<<endl;
}

virtual void f3()=0; //纯虚函数
};

class mySecond : public myFirst{
private:
    int value_mySecond;
public:
    mySecond(int s) : myFirst(s){
        value_mySecond = s;       
    }

void f1(){         //覆盖基类一般函数
cout<<"mySecond.f1()!"<<endl;
}

void f2(){         //覆盖基类虚函数
cout<<"mySecond.f2()!"<<endl;
}
void f3(){         //覆盖基类纯虚函数
cout<<"mySecond.f3()!"<<endl;
}
};

int _tmain(int argc, _TCHAR* argv[])
{
//myFirst *mf = new myFirst(1); //抽象类不能创建对象
mySecond *ms = new mySecond(1);

ms->f1(); //mySecond.f1()!
ms->f2(); //mySecond.f2()!
ms->f3(); //mySecond.f3()!

    //向上转型采用强类型转换
((myFirst *)ms)->f1(); //myFirst.f1()!
((myFirst *)ms)->f2(); //mySecond.f2()!
((myFirst *)ms)->f3(); //mySecond.f3()!

return 0;
}

=============================

java示例

java提供了抽象方法的机制abstract method,这种方法不完整,仅有声明
没有方法体
abstract void f();
包含抽象方法的类叫抽象类,如果类中包含一个或多个抽象方法,则该类必
须被声明为抽象类,用abstract来修饰抽象类。
如果从一个抽象类继承,并创建这个新类的对象,必须给抽象基类中所有抽
象方法提供方法定义,否则,派生类也是抽象类,也用abstract修饰。

package com;

abstract class myFirst{
    int value_myFirst;
    public myFirst(int f){
        value_myFirst = f;   
    }
    public void f1(){
        System.out.println("myFirst.f1()!");    
    } 
    public abstract void f2();    //抽象方法   
}

//继承采用extends关键字
class mySecond extends myFirst{
    int value_mySecond;
    public mySecond(int s){
        //传递给基类构造函数时,采用super关键字,而且必须是第一条语句。
        super(s); 
        value_mySecond = s;               
    }
    public void f1(){
        System.out.println("mySecond.f1()!");    
    } 
    
    public void f2(){ //覆盖基类抽象方法
        System.out.println("mySecond.f2()!");     
    }   
}

//如果不实现基类抽象方法,那么此派生类也必须用abstract修饰
abstract class myThird extends myFirst{ 
    int value_myThird;
    public myThird(int t){        
        super(t); 
        value_myThird = t;               
    }
    public void f1(){
        System.out.println("myThird.f1()!");    
    }     
}

public class myCon{
    public static void main(String[] args){
        
        //myFirst mf = new myFirst(1); //抽象函数不能创建对象
        mySecond ms = new mySecond(1);
        //myThird mt = new myThird(1); 
        
        ms.f1(); //mySecond.f1()!
        ms.f2(); //mySecond.f2()!
        
        ((myFirst)ms).f1(); //mySecond.f1()!
        ((myFirst)ms).f2(); //mySecond.f2()!
    }
}


关于抽象方法和抽象类java和C#比较类似;
而C++叫纯虚函数和抽象类。


四、接口
C++中的没有接口的概念,它本身就可以多继承。

java中接口interface比抽象类abstract更进了一步,可看做"纯粹的抽象类"。
它允许创建者为一个类建立其形式,方法名,参数列表,返回类型,但没有
任何方法体。接口中也可以包含成员函数,但是他们都是隐含的public和
final。

创建接口时用interface来代替class,前面可以有public,如果不加访问权
限,那么它就是默认的包访问权限。
接口中的方法默认为public。

类实现接口要用implements关键字。

接口便于实现多重继承的效果,此处不作具体讨论。

package com;

interface myFirst{
    int value_myFirst=1;    
    public void f1();
}

class mySecond implements myFirst{
    int value_mySecond;
    public mySecond(int s){        
        value_mySecond = s;               
    }
    public void f1(){
        System.out.println("mySecond.f1()!");    
    }
}

public class myCon{
    static void play(myFirst mf){
        mf.f1();   
    }
    public static void main(String[] args){
        
        
        //myFirst mf = new myFirst(1);
        mySecond ms = new mySecond(1); 
        
        ms.f1();   //mySecond.f1()!       
        play(ms); //向上转型 mySecond.f1()!
        
        ((myFirst)ms).f1(); ////向上转型 mySecond.f1()!
    }
}

posted on 2011-04-08 18:43 luis 阅读(270) 评论(0)  编辑 收藏 引用

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2011年4月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

常用链接

留言簿(3)

随笔分类

随笔档案

文章分类

文章档案

友情链接

搜索

  •  

最新评论

阅读排行榜

评论排行榜