A a = new B();哪位给讲讲

ldpldy 2005-10-13 08:54:09
class Class1
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
{
//
// TODO: 在此处添加代码以启动应用程序
//
A a = new B();
a.name();
Console.ReadLine();
}
}
public class A
{
public A()
{
Console.WriteLine("aa");
}
public virtual void name()
{
Console.WriteLine("aname");
}
}
public class B:A
{
public B()
{
Console.WriteLine("bb");
}
public override void name()
{
Console.WriteLine("bname");
}
}

输出结果:
aa
bb
bname

为什么会输出aa?那位给讲讲执行原理,
...全文
250 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
fox7805034 2005-10-27
  • 打赏
  • 举报
回复
((A)this).name();//这句有错,没见过这样写法,如果想访问基类A,这样写base.name();
才会出现下面的
----------------------
aa
bb
aname
bname
~bb
~aa
--------------
iuhxq 2005-10-13
  • 打赏
  • 举报
回复
说楼主的问题简单的,我到想考考你们:

using System;
class Class1
{
[STAThread]
static void Main(string[] args)
{
A a = new B();
a.name();
Console.ReadLine();
}
}
public class A
{
public A()
{
Console.WriteLine("aa");
}
~A()
{
Console.WriteLine("~aa");
}
public virtual void name()
{
Console.WriteLine("aname");
}
}
public class B:A
{
public B()
{
Console.WriteLine("bb");
}
~B()
{
Console.WriteLine("~bb");
}
public override void name()
{
((A)this).name();
Console.WriteLine("bname");
}
}

上面代码如果不运行,谁能说出运行结果?
ldpldy 2005-10-13
  • 打赏
  • 举报
回复
关键就是A a = new B(); 的执行,讨论重点因该放在这里
new 只是分配了B的内存,
如果要是
A a = new B();
B a = new B();
这两个new B();分配的一不一样呢?
第二个new还要不要先构造的是B的父类的构造体,然后才是B的构造体呢?
eyych 2005-10-13
  • 打赏
  • 举报
回复
单A a = new B();这一句,

那a运行时是A还是B呢?


----------

当然是B了。
fox7805034 2005-10-13
  • 打赏
  • 举报
回复
析构的刚好相反:先子类在父类。。。。还有什么不明白嘛?
iuhxq 2005-10-13
  • 打赏
  • 举报
回复
单A a = new B();这一句,

那a运行时是A还是B呢?
iuhxq 2005-10-13
  • 打赏
  • 举报
回复
swordragon(古道热肠) 说的似乎很容易理解,但我觉得原理实际不是那么简单
iuhxq 2005-10-13
  • 打赏
  • 举报
回复
晕,我第一个说错了,大家不要讨论我说那句了

带析构的结果:
aa
bb
bname
~bb
~aa
swordragon 2005-10-13
  • 打赏
  • 举报
回复
A a = new B();
首先构造的是B的父类的构造体,然后才是B的构造体,所以输出:
aa
bb

a.name();
由于B中重载了父类A的name方法,所以,输出
bname
iuhxq 2005-10-13
  • 打赏
  • 举报
回复
using System;
class Class1
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
{
//
// TODO: 在此处添加代码以启动应用程序
//
A a = new B();
a.name();
Console.ReadLine();
}
}
public class A
{
public int x;
public A()
{
Console.WriteLine("aa");
}
~A()
{
Console.WriteLine("~aa");
}
public virtual void name()
{
Console.WriteLine("aname");
}
}
public class B:A
{
public B()
{
x = 10;
Console.WriteLine("bb");
}
~B()
{
Console.WriteLine("~bb");
}
public override void name()
{
Console.WriteLine("bname");
}
}
辉说慧语 2005-10-13
  • 打赏
  • 举报
回复
有必要加深语法学习:)
fox7805034 2005-10-13
  • 打赏
  • 举报
回复
中和上面两位楼主的。。。
ldpldy 2005-10-13
  • 打赏
  • 举报
回复
new 是在托管堆上分配B类型所需的内存空间,返回一个指向新创建对象的引用,保存在a中,
这样a.name();就不难理解了,
如 iuhxq(小灰(http://blog.csdn.net/iuhxq)) 所说,
那么B a = new B();是不是也要先调用子类构造函数,再调用父类构造函数呢?
iuhxq 2005-10-13
  • 打赏
  • 举报
回复
参考一下:

10.5.4 重写方法若一个实例方法声明中含有 override 修饰符,则称该方法为重写方法。重写方法用相同的签名重写所继承的虚拟方法。虚拟方法声明用于引入新方法,而重写方法声明则用于使现有的继承虚拟方法专用化(通过提供该方法的新实现)。

由 override 声明所重写的那个方法称为已重写了的基方法。对于在类 C 中声明的重写方法 M,已重写了的基方法是通过检查 C 的各个基类确定的,检查的方法是:先从 C 的直接基类开始,逐个检查每个后续的直接基类,直至找到一个与 M 具有相同签名的可访问方法。为了查找已重写了的基方法,可访问方法可以这样来定义:如果一个方法是 public、是 protected、是 protected internal,或者是 internal 并且与 C 声明在同一程序中,则认为它是可访问的。

除非下列所有项对于一个重写声明皆为真,否则将会出现编译时错误:

可以按照上面描述的规则找到一个已重写了的基方法。
该已重写了的基方法是一个虚拟、抽象或重写方法。换句话说,已重写了的基方法不能是静态或非虚拟方法。
已重写了的基方法不是密封方法。
重写声明和已重写了的基方法具有相同的返回类型。
重写声明和已重写了的基方法具有相同的声明可访问性。换句话说,重写声明不能更改所对应的虚拟方法的可访问性。
重写声明可以使用基访问(第 7.5.8 节)访问已重写了的基方法。在下面的示例中

class A
{
int x;
public virtual void PrintFields() {
Console.WriteLine("x = {0}", x);
}
}
class B: A
{
int y;
public override void PrintFields() {
base.PrintFields();
Console.WriteLine("y = {0}", y);
}
}
在 B 中的调用 base.PrintFields() 就调用了在 A 中声明的 PrintFields 方法。基访问禁用了虚拟调用机制,它只是简单地将那个重写了的基方法视为非虚拟方法。如果把 B 中的调用改写成 ((A)this).PrintFields(),它将递归调用在 B 中声明而不是在 A 中声明的 PrintFields 方法,这是因为 PrintFields 是虚拟的,而且 ((A)this) 的运行时类型为 B。

只有在包含了 override 修饰符时,一个方法才能重写另一个方法。在所有其他情况下,声明一个与继承了的方法具有相同签名的方法只会使那个被继承的方法隐藏起来。在下面的示例中

class A
{
public virtual void F() {}
}
class B: A
{
public virtual void F() {} // Warning, hiding inherited F()
}
B 中的 F 方法不包含 override 修饰符,因此不重写 A 中的 F 方法。相反,B 中的 F 方法隐藏 A 中的方法,并且由于该声明中没有包含 new 修饰符,从而会导致一个警告。

在下面的示例中

class A
{
public virtual void F() {}
}
class B: A
{
new private void F() {} // Hides A.F within B
}
class C: B
{
public override void F() {} // Ok, overrides A.F
}
B 中的 F 方法隐藏从 A 继承的虚拟 F 方法。由于 B 中的新 F 具有私有访问权限,它的范围只包括 B 的类体而没有延伸到 C。所以,允许 C 中的 F 声明重写从 A 继承的 F。

yeskele 2005-10-13
  • 打赏
  • 举报
回复
子类的过程Name是override父类的过程Name,也就是覆盖父类的过程。所以输出的是bname
alien54155415 2005-10-13
  • 打赏
  • 举报
回复
构造函数的执行顺序:先祖先(基类),再客人(对象成员),后自己(派生类本身)
iuhxq 2005-10-13
  • 打赏
  • 举报
回复
aa
bb
这两个应该容易理解
先调用子类构造函数,再调用父类构造函数

62,056

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧