积极答复者
关于非默认构造函数问题

问题
答案
-
同时还要指出你给我的实例做出如下修改就更能说明base指定对从基类到派生类构造函数的执行序列的执行的控制,你的代码修改如下:
//基类
public class MyBaseClass
{
public int ID; //有一个ID属性//有一个ID属性//基类默认构造函数
public MyBaseClass()
{}
//父类构造自己的属性 ID
public MyBaseClass(int id )
{
ID = id;
}
}
//子类
public class MyDerivedClass : MyBaseClass
{
public string Name; //有一个Name属性
public MyDerivedClass(int id, string Name)
: base(id) //把初始化id的工作交给基类,子类就不用再操心了
{
Name = name;//子类自己处理name
}
}
//////测试代码
MyDerivedClass subObj = new MyDerivedClass( 1, "Jack");
MyDerivedClass subObj = new MyDerivedClass( 2, "Tom");这里面如果不在继承类里面指定base(id),那么构造函数的执行序列是这样的:
先执行system.object.object()构造函数,然后执行MyBaseClass.MyBaseClass(),最后执行 MyDerivedClass(int id, string Name)。
如果我们在派生类非默认构造函数中加了bese(id),那么构造函数的执行序列就按我们意愿设定的顺序执行了即如下:
先执行system.object.object()构造函数,然后执行MyBaseClass.MyBaseClass(int id),最后执行 MyDerivedClass(int id, string Name)。
这就是我说的关键字base的意义,(请注意我讨论的是意义不是用法,这是两回事)可通过关键字base指定基类构造函数初始化器改变构造函数执行序列是其意义之一,指定某一参数在基类中先行执行,减少派生类中构造函数的工作量和简化代码,这就是base的意义之二。
万物皆变,规则永恒。- 已标记为答案 wavetekgroup 2011年3月6日 2:06
全部回复
-
您好,构造函数不能被继承,需要增加一个构造函数:
public class MyDerivedClass : MyBaseClass
{
public MyDerivedClass(int i, int j)
: base(i)
{
}public MyDerivedClass(int i)
: base(i)
{
}
}或
public class MyDerivedClass : MyBaseClass
{
public MyDerivedClass(int i, int j)
: base(i)
{
}public MyDerivedClass(int i)
: this(i, 0)
{
}
} -
-
在继承的层次结构中,子类必需调用基类的构造函数。
即使您看到很多子类没有调用base,那是因为基类中包含有默认的构造函数(即不带参数的构造函数)。
当基类中不存在默认的构造函数时,就需要调用base(*),这就是base(i)的意义,本例子中基类没有构造函数,所以需要指明。
再给个知识点:如果在代码中不写构造函数,那么自动包含一个不带参数的构造函数,如果写了构造函数,则默认的构造函数需要显示声明。
另外我上面说的各自处理,这是一种情况,根据设计的目的不同,也有可能只在基类中处理,在子类中可以继承处理后的结果。
- 已标记为答案 feiyun0112Moderator 2011年3月4日 1:00
- 取消答案标记 wavetekgroup 2011年3月4日 17:31
-
在继承的层次结构中,子类必需调用基类的构造函数。
即使您看到很多子类没有调用base,那是因为基类中包含有默认的构造函数(即不带参数的构造函数)。
当基类中不存在默认的构造函数时,就需要调用base(*),这就是base(i)的意义,本例子中基类没有构造函数,所以需要指明。
再给个知识点:如果在代码中不写构造函数,那么自动包含一个不带参数的构造函数,如果写了构造函数,则默认的构造函数需要显示声明。
另外我上面说的各自处理,这是一种情况,根据设计的目的不同,也有可能只在基类中处理,在子类中可以继承处理后的结果。
谢谢你的解答,但我对你的解答有不同看法,
首先我们回到构造函数的本质,构造函数的根本目的是对类对象进行初始化设置,最基本的任务之一比如对一些变量进行初始赋值,通过非默认构造函数参数对变量赋值是一个途径,因此为了减少参数在派生类里参数代码的复杂性,尤其多个参数,可通过关键字base指定基类构造函数初始化器改变构造函数执行序列是其意义之一,指定某一参数在基类中先行执行,减少派生类中构造函数的工作量和简化代码,这就是base的意义之二。(假定上面例子里基类和派生类里的 int i 具有相同含义,当然也可以不同,就如你所说:并无直接关系,只是值传递,基类和派生类接收到 i 值后自行处理。)
当然你说的也没错,如果没有默认构造函数只有非默认构造函数就需要调用base,但这我认为不是base的本质意义,因为不指定编译器会报错滴,因为编译器有其他构造函数就不会执行自建默认构造函数的工作,但是如果不指定它又不知道执行哪个非默认构造函数,当然找不到默认构造函数也不会按默认序列执行,这也正是我们想控制构造执行序列顺序的目的。
不知道我理解的是否正确,还请指正。
万物皆变,规则永恒。 -
//估计是两个相同数据类型的int参数,而且使用了毫无实际意义的i和j变量名,因此把你搞晕了。如果换一个角度你就很容易理解了: //基类 public class MyBaseClass { public int ID; //有一个ID属性 //父类构造自己的属性 ID public MyBaseClass(int id ) { ID = id; } } //子类 public class MyDerivedClass : MyBaseClass { public string Name; //有一个Name属性 public MyDerivedClass(int id, string Name) : base(id) //把初始化id的工作交给基类,子类就不用再操心了 { Name = name;//子类自己处理name } } //////测试代码 MyDerivedClass subObj = new MyDerivedClass( 1, "Jack"); MyDerivedClass subObj = new MyDerivedClass( 2, "Tom"); -------------------------------------------------------------------------------- 信奎爷,无所畏惧!
- 已建议为答案 Charles Shao 2011年3月5日 4:46
-
补充一下,在C#中,子类调用自己或自己基类的其它构造函数是有效的,也就是可以在构造时重用其它构造函数。
但是如果是在C++中的话, 如果你在构造函数中调用其它任何构造函数的话。 表面上编译不会出错,但是实际运行后你会发现,调用其它构造函数是无效的!
C++说,我们自立更生,别人不准插手! 哈哈^o^
信奎爷,无所畏惧!!- 已建议为答案 Charles Shao 2011年3月5日 4:51
-
同时还要指出你给我的实例做出如下修改就更能说明base指定对从基类到派生类构造函数的执行序列的执行的控制,你的代码修改如下:
//基类
public class MyBaseClass
{
public int ID; //有一个ID属性//有一个ID属性//基类默认构造函数
public MyBaseClass()
{}
//父类构造自己的属性 ID
public MyBaseClass(int id )
{
ID = id;
}
}
//子类
public class MyDerivedClass : MyBaseClass
{
public string Name; //有一个Name属性
public MyDerivedClass(int id, string Name)
: base(id) //把初始化id的工作交给基类,子类就不用再操心了
{
Name = name;//子类自己处理name
}
}
//////测试代码
MyDerivedClass subObj = new MyDerivedClass( 1, "Jack");
MyDerivedClass subObj = new MyDerivedClass( 2, "Tom");这里面如果不在继承类里面指定base(id),那么构造函数的执行序列是这样的:
先执行system.object.object()构造函数,然后执行MyBaseClass.MyBaseClass(),最后执行 MyDerivedClass(int id, string Name)。
如果我们在派生类非默认构造函数中加了bese(id),那么构造函数的执行序列就按我们意愿设定的顺序执行了即如下:
先执行system.object.object()构造函数,然后执行MyBaseClass.MyBaseClass(int id),最后执行 MyDerivedClass(int id, string Name)。
这就是我说的关键字base的意义,(请注意我讨论的是意义不是用法,这是两回事)可通过关键字base指定基类构造函数初始化器改变构造函数执行序列是其意义之一,指定某一参数在基类中先行执行,减少派生类中构造函数的工作量和简化代码,这就是base的意义之二。
万物皆变,规则永恒。- 已标记为答案 wavetekgroup 2011年3月6日 2:06
-
呵呵,首先声明执行序列不是偶的发明,这是很多书籍上的提法。至于为啥提问就是因为看了这些书上的这一讲解中提到关键字base的使用,但又没有讲解的很详细,所以一头雾水,因此发问,经过各位的指点,我又反复结合书上的终于顿悟了base用法在构造函数执行序列中的实质意义,就是这样,我现在明白了,你说的不错,一个问题可以从不同角度解释,从函数的角度就是相关的函数之间的关系,但从高一些的角度是执顺序的关系,即执行序列的关系。我并不是否定或反驳你,(偶只是一个菜鸟,没有哪个水平,呵呵)你解释的更微观一些,书上讲解的更宏观一些,因此结合你的讲解,我才领悟的全面起来。所以这里要谢谢你,还希望以后多多指教。
-
指教不敢,一起讨论问题,共同进步。
- 已标记为答案 wavetekgroup 2011年3月6日 2:06
- 取消答案标记 wavetekgroup 2011年3月8日 3:01
-