override与new的区别

昨天参加面试,遇到一个关于new修饰符的题,由于本人不慎,给搞错了,纠其原因,还是因为我的C#基础知识不牢固,关于override与new的区别平时没有太注意。在此,为大家分享一下:
代码如下:

 public class baseClass
    
{
        
public baseClass()
        
{
            Method1();
        }

        
public virtual void Method1()
        
{
            Console.WriteLine(
"Method1 in baseClass");
        }

    }


    
public class derivedClass : baseClass
    
{
        
private int value;
        
public derivedClass()
        
{
            value 
= 2;
        }

        
public override void Method1()
        
{
            
if (value == 2)
                Console.WriteLine(
"value==2");
            
else
                Console.WriteLine(
"value!=2");           
        }

    }


问题:
1、初始化一实例:baseClass tempClass=new derivedClass()之后,会输出什么结果?
2、把derivedClass类中的override换成 new之后,又会输出什么结果?

正确答案:
1、value!=2
2、Method1 in baseClass
MSDN上说:new 关键字在用作修饰符时,可以显式隐藏从基类继承的成员。隐藏继承的成员意味着该成员的派生版本将替换基类版本。也就是说,在用new关键字时,派生类与基类的这两个相同签名的方法已经没有任何联系了。
而用override时,它与new的区别主要是,overrid是重写了基类的方法,new是隐藏、覆盖了基类的方法。。

posted on 2007-11-07 17:10 任力 阅读(587) 评论(15)  编辑 收藏 所属分类: C、.NET FrameworkB、ASP.NET 2.0

评论

#1楼  2007-11-20 13:02 無尽海      

我觉得你说得还不是很清楚

new是隐藏当前类继承来的方法,隐藏的原来方法还是存在

baseClass baseClass=new derivedClass();
会执行
Method1 in baseClass

override这是重写原来的方法
baseClass baseClass=new derivedClass();
以就是重写后的方法
value!=2

  回复  引用  查看    

#2楼  2007-12-13 16:59 任力 [未注册用户]

@無尽海
可能是吧,我对new与override的区别也只是了解个大概。谢谢指导。。   回复  引用    

#3楼  2008-01-25 20:06 Jack Lee [未注册用户]

我觉得还是有问题的.
baseClass aa = new derivedClass();之后
override的结果为: value!=2,value==2
new的结果为:Method1 in baseClass,Method1 in baseClass;

derivedClass bb = new derivedClass();之后
new的结果为:Method1 in baseClass;value==2
override的结果为: value!=2,value==2   回复  引用    

#4楼  2008-01-25 20:16 Jack Lee [未注册用户]

override是重写方法,无论是基类对象还是派生类对象都将调用重写后的方法.
new只是隐藏基类的方法,派生类看不到而已.但是基类对象还是调用自已原来的方法,派生类调用new之后的方法.
Jack Lee以后就是我的网名了.我是河南科技学院三月软件工作室的一员,我的名子是常军伟   回复  引用    

#5楼  2008-01-25 20:40 hoodlum1980      

(new)“隐藏”,(override)“覆盖”(重写),一楼说的有道理。不够要弄清楚这两个有什么区别确实也很难,因为它们的子类在使用的父亲的方法的时候根本看不出什么区别,反正子类不管父类是new了还是override了用的都是父类的方法。区别就在于,用父类的类型指针去访问子类的成员的时候有区别。

本质区别就是,一个子类的对象中,如果是new的,那么父类的这个函数地址仍然保留着,同时又提供了一个新的子类的该函数入口地址。也就是说子类对象中同时保存了两个入口地址,父类的该函数地址被“隐藏”,但是它还可以用父类的类型指针访问得到,用子类类型指针访问该函数则进入new出来那个函数入口。

如果是override的,表示对象中的这个地址是被改写的,也就是说子类中只能访问到自己定义的函数了。而base的函数地址我们现在没有办法拿到了,因为函数表这个地址被指向了自己定义的函数。因此只能访问到自身定义的该函数。

再向下继承的子类指针就和普通继承一样,没什么好说的了。
  回复  引用  查看    

#6楼  2008-01-25 20:40 hoodlum1980      

给你一段代码,你可以自己去测试一下,并想想结果。变量的命名规则是“指针类型_实际对象类型”,例如ba_c1表示这是一个指向c1对象的ba类型指针。c1_c1表示这是指向c1对象的c1类型指针。ba是base的缩写。

static void Main(string[] args)
{
BaseClass ba_c1 = new ChildClass1();
BaseClass ba_c2 = new ChildClass2();
//ChildClass1 c1_c3 = new ChildClass3();
ChildClass1 c1_c1 = (ChildClass1)ba_c1;
ChildClass2 c2_c2 = (ChildClass2)ba_c2;

// override
Console.Write("ba_c1:");
ba_c1.Func1();
Console.Write("c1_c1:");
c1_c1.Func1();

// new
Console.Write("ba_c2:");
ba_c2.Func1();
Console.Write("c2_c2:");
c2_c2.Func1();
Console.ReadLine();
}
}

public class BaseClass
{
public virtual void Func1()
{
Console.WriteLine(" Base.F1");
}
}

//改写Base.Func1的入口地址为ChildClass1.Fun1的地址。
public class ChildClass1 : BaseClass
{
public override void Func1()
{
Console.WriteLine(" (overrided) C1.myF1");
}
}

//ChildClass2.Fun1是一个新的入口地址,不会覆盖base.Fun1的地址。
public class ChildClass2 : BaseClass
{
public new void Func1()
{
Console.WriteLine(" (new) C2.newF1");
}
}   回复  引用  查看    

#7楼  2008-01-25 20:43 hoodlum1980      

上面的代码运行结果是:

ba_c1: (overrided) C1.myF1
c1_c1: (overrided) C1.myF1
ba_c2: Base.F1
c2_c2: (new) C2.newF1

可以看到,override的时候,父类指针的该函数地址被改写了,因此不管用父类还是子类的指针,进入的都是子类定义的函数。

而new时,用父类指针访问到的是父类定义的函数,用子类指针访问到的是自己定义的函数。因为对象中两个函数的地址可以用不同类型指针进行获取。   回复  引用  查看    

#8楼  2008-01-25 20:57 hoodlum1980      

override:
函数名: 地址
Base.F1: =C1.F1
C1.F1: ********

new:
Base.F1: ********
C2.F1 : ********

一个子类对象

_______________________________________________
|... ___________________......................................|
|...|父类成员...................| .....子类成员.....................|
|... --------------------- .......................................|
|______________________________________________|

............................|...............................|
..................override一个地址.............new一个地址在此处

请注意:访问成员函数的大概过程可以比喻为,基址->成员函数,->操作符将查函数地址表得到偏移量,返回该成员函数的入口地址,代码跳转到此处。->操作符在访问成员变量时,将返回一个和右边变量的类型像匹配的指针或数据类型。   回复  引用  查看    

#9楼 [楼主] 2008-01-25 21:17 任力      

@Jack Lee
override是重写方法,无论是基类对象还是派生类对象都将调用重写后的方法.
new只是隐藏基类的方法,派生类看不到而已.但是基类对象还是调用自已原来的方法,派生类调用new之后的方法.
没错,override与new是这样理解的。至于下面这几句:

我觉得还是有问题的.
baseClass aa = new derivedClass();之后
override的结果为: value!=2,value==2
new的结果为:Method1 in baseClass,Method1 in baseClass;

derivedClass bb = new derivedClass();之后
new的结果为:Method1 in baseClass;value==2
override的结果为: value!=2,value==2
就不对了,
首先,将子类对象不论是赋给本身类的对象,还是基类的对象,它的结果应是一样的(生成对象时)。但涉及到override于new,当它调用方法时,结果才可能不一样。
再则,创建对象时,Method1()方法只可能执行一次,不可能有两个结果。

看一下它的执行过程:
baseClass aa = new derivedClass();
override时,
执行顺序:derivedClass.Method1()(基类的被覆盖了)-->derivedClass();
所以结果应该是value!=2
new时,
执行顺序:baseClass.Method1()-->derivedClass();
所以结果应该是:Method1 in baseClass

  回复  引用  查看    

#10楼  2008-01-25 22:33 hoodlum1980      

题目里面加了一个value成员,应该是考你new一个对象时候的调用顺序,先父类构造函数,再子类构造函数。还有就是定义时未赋值时,value的默认初始值是0,指针是NULL。   回复  引用  查看    

#11楼 [楼主] 2008-01-26 09:00 任力      

@hoodlum1980
是的。分析的不错。
考的是创建对象的调用顺序。value的默认初始值是0,指针是null。   回复  引用  查看    

#12楼  2008-03-07 22:26 情缘      

偶明白了!!!   回复  引用  查看    

#13楼  2008-04-15 12:25 c.life      

看了大家的回复也发下我的理解
两个考点:基类继承类调用和(new override)。
且看上面试题,姑且把这两个类分别叫
baseClass 基类,
derivedClass 派生类
这个时候,我们明确一下派生类的概念,派生类既有自己的特性又有基类的特性。(其实派生类这个对象同时具有两个类的数据和行为,把这种能力我们称为多态性。)
好了,看试题.
1、初始化一实例:baseClass tempClass=new derivedClass()之后,会输出什么结果?
这里我们看到实际是(new derivedclass)结果赋给tempclass.
这个时候看derivedClass类override基类的方法method1()
执行:
从基类method1()-->派生类重写基类的Method1()显示的结果就是:value!=2;
其实这个时候派生类会继续着执行DerivedClass()方法,结果:value的值为2.到此类执行完毕.
2.、把derivedClass类中的override换成 new之后,又会输出什么结果?
msdn:new 和 override这两个修饰符在含义上相互排斥。使用 new 会用同样的名称创建一个新成员并使原始成员变为隐藏的,而 override 则扩展继承成员的实现。
如果继承类使用new method1() 只能说是继承类自己创建了以个新方法,和基类没关系了.
执行:
从基类method1()-->基类public virtual void Method1()显示的结果就是:Method1 in baseClass;
至于派生类的new method1()这个原本是基类的成员被隐藏掉了.如果想访问,可以把派生类的实例直接访问。
不知道我的理解有什么错误地方,请指正.
  回复  引用  查看    

#14楼  2008-05-27 11:24 StephenJu      

那构造函数也执行了啊,不是给value重新赋值了吗??怎么结果??   回复  引用  查看    

#15楼  2008-05-27 12:11 StephenJu      

哦,明白了,输出结果是对的,我以为是问value的值呢,SORRY!
学习了!!   回复  引用  查看    


标题  
姓名  
主页
Email (只有博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2007-12-13 16:39 编辑过
 
 


导航

公告

IT新闻:

细节,仍然是细节,细节决定成败 8-20 20:41
<2008年3月>
2425262728291
2345678
9101112131415
16171819202122
23242526272829
303112345

统计

与我联系

搜索

 

常用链接

我参与的团队

随笔分类(23)

新闻分类(148)

相册

收藏夹(12)

Friend

Web标准

外语偶像

最新随笔

最新评论

阅读排行榜

评论排行榜