构造函数和析构函数规模应该尽可能小型化?????
在VCKBASE.COM 中看到如下文章:
原文:
在设计类的时候,应该考虑今后有一天这个类可能成为其它类的基类。当从某个基类派生类的时候,基类的析构和构造函数分别被暗中拷贝到派生类的构造函数和析构函数。与普通的成员函数相反,它们可以被改写(假设它们是虚拟的)或者完全不调用,基类的构造函数和析构函数是自动被调用的。所以最好不要强制派生对象之所不欲,而是一定要使用它。换句话说,构造函数和析构函数实现的功能应该最小化,构造和销毁,不要画蛇添足。例如,对于一个支持序列化(将内容写入文件)的串类,不要在其构造函数中打开/创建文件。这种操作应该留给专门的成员函数来做,所以当创建新的派生类时,如 ShortString(用于保存定长串,像文件名),其构造函数将不会被强制实现任何多余的从基类继承的文件I/O操作。
原文结束-----------
我的疑惑:
1。"当从某个基类派生类的时候,基类de构造函数被暗中
拷贝到派生类的构造函数"中去??
不会吧?
如果我有:
class A
{
int i,j;
public A(int i1,int j1)
{
i=i1;
j=j1;
}
public A(int i1)
{
i=i1;
j=0;
}
}
class B ; A
{
public b(int i1,int j1)
{
i=i1+100;
j=j1+199999;
}
}
试问怎么个拷贝法?????
2."基类的构造函数是自动被调用的"
果真如此的话,那么我在msdn上发现:
public Cylinder(double radius, double height): base(radius, height)
{
}
其中Cylinde是Cshape的派生类
那么既然是“自动调用”,我何不写成
public Cylinder(double radius, double height)
{
}
要不怎么说是“自动调用”呢??
注意我这里反复强调“自动”
问题点数:100、回复次数:7Top
1 楼TheAres(班门斧)回复于 2003-08-01 01:28:19 得分 100
1,你看看如下的程序,在产生一个B对象的时候,是会先调用B的父类的构造函数。如果不是把父类A中的函数在B中实现,如何执行。所以肯定是拷贝的,只不过是隐含的。具体拷贝过去函数是什么,这个不知道,我猜想大约是什么***Init***的函数。
// cs_attribute_obsolete.cs
// CS0619 expected
using System;
class A
{
public int i,j;
public A()
{
Console.WriteLine("A:A()");
}
public A(int i1,int j1)
{
i=i1;
j=j1;
Console.WriteLine("A:A(int,int");
}
public A(int i1)
{
i=i1;
j=0;
Console.WriteLine("A:A(int)");
}
}
class B : A
{
public B(int i1,int j1)
{
i=i1+100;
j=j1+199999;
Console.WriteLine("B:B(int,int)");
}
}
class C
{
public static void Main()
{
B b = new B(1,1);
Console.ReadLine();
}
}
2."基类的构造函数是自动被调用的"
什么不写就是自动调用。你显式的指定就不会自动了。
public Cylinder(double radius, double height)//自动
{
}
public Cylinder(double radius, double height): base(radius, height)//显式
{
}
Top
2 楼yujianxueren(.)回复于 2003-08-01 11:07:01 得分 0
To TheAres(班门斧):
你斧头大哥的回答果然没错,的确是暗中调用了,因为按照大哥的程序,
输出为:
A:A()
B:B(int,int) ,但是我现在还有疑惑,还望大家指导。
class A1
{
public int i,j;
public A1()
{
Console.WriteLine("A:A()");
}
public A1(int i1,int j1)
{
i=i1;
j=j1;
Console.WriteLine("A:A(int,int)---------{0},{1}",i,j);
}
public A1(int i1)
{
i=i1;
j=0;
Console.WriteLine("A:A(int)");
}
}
class B1 : A1
{
//呵呵,俺把它注释调,反正他会继承父亲A1的无参数的构造函数的
// public B1()
// {
// Console.WriteLine("B:B()");
// }
public B1(int i1,int j1)//:base(i1,j1)
{
i=i1+100;
j=j1+199;
Console.WriteLine("B:B(int,int)----{0},{1}",i,j);
}
}
class C1:B1
{
public C1()
{
Console.WriteLine("C;C()");
}
public C1(int i1,int j1)
{
Console.WriteLine("C;C(int ,int)");
}
}
public class test
{
public static void Main()
{
C1 c=new C1 (1,1);
Console.ReadLine();
}
public test()
{
}
}
呵呵,程序竟然报错,说“重载B1方法未获得0参数”!!
B1不是可以继承A1的0参数构造函数吗?
是不是“直接基类”必须实现不带参数的构造函数啊?
继续往下面看:
class A1
{
public int i,j;
//我就是要想方设法的注释掉0参数构造函数,呵呵
//public A1()
//{
// Console.WriteLine("A:A()");
//}
public A1(int i1,int j1)
{
i=i1;
j=j1;
Console.WriteLine("A:A(int,int)---------{0},{0}",i,j);
}
public A1(int i1)
{
i=i1;
j=0;
Console.WriteLine("A:A(int)");
}
}
class B1 : A1
{
public B1(int i1,int j1):base(i1,j1)
{
i=i1+100;
j=j1+199;
Console.WriteLine("B:B(int,int)----{0},{0}",i,j);
}
}
public class test
{
public static void Main()
{
B1 b = new B1(1,1);
Console.ReadLine();
}
public test()
{
}
}
这回可没有出现错误了,因为我强制它调用基类的public A1(int i1,int j1),
所以编译器就没有机会再“自做多情”的调用基类的0参数构造函数了
好,下面假设我有三个类:爷类,父类,孙类 (大家别笑啊)
1。如果我在爷类中没有实现0参数构造函数,父类和孙类就都甭想实现
0参数构造函数,并且父类和孙类的“非0参数构造函数”都必须“强制性”
的调用爷类的“非0参数构造函数”?????
2。如果我在爷类中实现了0参数构造函数,但是父类中没有实现,此刻,
孙类还是甭想实现0参数构造函数????
也就是说,我在类的设计中,必须实现类的0参数构造函数,否则的话,
它的后代永远没有机会实现0参数构造函数????0参数构造函数就会
"断子绝孙",它的后代,每实现一个“非0参数构造函数”,就必须
"强制性"调用父类的"非0参数构造函数",以此作为代价!!!?????
3。VCKBASE.COM 所说的"当从某个基类派生类的时候,基类de构造函数被暗中
拷贝到派生类的构造函数中去"
其实是说,如果派生类的构造函数没有“显式”的调用父类的“构造函数”,
则会发生这种“暗中拷贝”的问题,而一旦你“显式”的调用了父类的“构造函数”,
派生类是不会多此一举的?????????
Top
3 楼TheAres(班门斧)回复于 2003-08-01 22:32:01 得分 0
1,
>>呵呵,程序竟然报错,说“重载B1方法未获得0参数”!!
问题出在你注释的地方,你把没有任何参数的B的构造函数去了,对于从B继承的C来说就出问题了,因为它缺省要调用B的无参数的构造函数。
>>1。如果我在爷类中没有实现0参数构造函数,父类和孙类就都甭想实现
>> 0参数构造函数,并且父类和孙类的“非0参数构造函数”都必须“强制性”
>> 的调用爷类的“非0参数构造函数”?????
没有爷类的概念,记住只有父类的概念,一层一层的找。如果A->B, B->C,例子如下,就可以。
// cs_attribute_obsolete.cs
// CS0619 expected
using System;
class A1
{
public int i,j;
// public A1()
// {
// Console.WriteLine("A:A()");
// }
public A1(int i1,int j1)
{
i=i1;
j=j1;
Console.WriteLine("A:A(int,int)---------{0},{1}",i,j);
}
public A1(int i1)
{
i=i1;
j=0;
Console.WriteLine("A:A(int)");
}
}
class B1 : A1
{
public B1():base(0,0)
{
Console.WriteLine("B:B(int,int)----{0},{1}",i,j);
}
}
class C1:B1
{
public C1()
{
Console.WriteLine("C;C()");
}
public C1(int i1,int j1)
{
Console.WriteLine("C;C(int ,int)");
}
}
public class test
{
public static void Main()
{
C1 c=new C1 (1,1);
Console.ReadLine();
}
public test()
{
}
}
Top
4 楼TheAres(班门斧)回复于 2003-08-01 22:35:38 得分 0
>>2。如果我在爷类中实现了0参数构造函数,但是父类中没有实现,此刻,
孙类还是甭想实现0参数构造函数????
不一定。见上面的例子。
>> 也就是说,我在类的设计中,必须实现类的0参数构造函数,否则的话,
>> 它的后代永远没有机会实现0参数构造函数????0参数构造函数就会
>> "断子绝孙",它的后代,每实现一个“非0参数构造函数”,就必须
>> "强制性"调用父类的"非0参数构造函数",以此作为代价!!!?????
父类没有,子类照样有。你只要指明白子类要调用拿一个父类构造函数就可以了,用base指定。
比如上面例子中的B1 和A1.
Top
5 楼TheAres(班门斧)回复于 2003-08-01 22:40:35 得分 0
>>3。VCKBASE.COM 所说的"当从某个基类派生类的时候,基类de构造函数被暗中
>> 拷贝到派生类的构造函数中去"
>> 其实是说,如果派生类的构造函数没有“显式”的调用父类的“构造函数”,
>> 则会发生这种“暗中拷贝”的问题,而一旦你“显式”的调用了父类的“构造函数”,
>> 派生类是不会多此一举的?????????
面上说的,就想你说的这样。估计实际编译的时候,可能就想文章上说的那样,是要拷贝一个函数去的。具体的编译步骤,我没有资料,也不是很熟。
估计这篇文章是用C++说的吧,最早C++的编译是先转换成c代码,然后编译的。你想想,C中完全没有OO的语法支持,肯定是产生了一个什么函数,来实现这一套的。
欢迎继续讨论,我把这个帖子转到C#去,看看大家有什么说法。
Top
6 楼yujianxueren(.)回复于 2003-08-02 09:44:11 得分 0
谢谢斑竹!Top
7 楼yujianxueren(.)回复于 2003-08-05 21:36:18 得分 0
最后一次up
要不,我明天结帐Top




