如题目所说:在基类中定义的虚方法,在派生类中即然可以重写,也可以不重写,而且派生类中可以随时扩展方法,所以我让为虚(virtual)太多余了。请前辈,给我说说,我想的对不。在线,明白了立即给分。
解决方案 »
- 新闻图片切换
- office control 怎么使用?
- 关于上传文件的MIME问题
- 如何不利用FileUpload实现上传文件的功能?
- 发现一个台湾的.net视频教学网站!发出来共享!
- 原来的VS.net由Win优化大师优化出错,不能用了,然后再装就装不上了,该怎么办呢?
- 程序动态创建控件数组???高手来看看
- sorting 和 paging 的疑问
- 网上119!(火警)请问谁知道将两个系统控件做在一起!(加分的哦)
- 通过ajax或者script来实现修改数据库
- 数据库使用了nvarchar(MAX)时,asp.net(C#)中cmd.Parameters.Add该如果使用?
- 求一正则表达式 大于0小于等于100 小数点两位
clash one
{
public one()
{
}
public virtual void method()
{
Console.Write(" method");
}
}
class two:one
{
public override void method()
{
Console.Write("override method");
}
}如果我在one 类中没有用public virtual void method(),而是在two类中直接产生
public void method()
{}效果,不是一样的吗?也就是我,说的,virtual是多余的,因为派生只要愿意,随时都可以,生明一个方法。
是的 可以重写也可不重写 用virtual只是告诉你这个类或者这个方法可以任你扩展
=============================================================================您上面的话“可以任你扩展”,我承认是对的,但是派生类可以随时扩展基类,那么要virtual还有什么意义??
如果one中有必须实现的方法,那么必须要继承它喽,可是Virtual的存在就是不那么可推敲了。有它,和没有它,派生类都不受影响,您能给指一个virtual真正有用的例子吗??或是说明它的真正发明用处。
效果不一样!
只有virtual方法可以override
没有override关键字相当于省略了new关键字,实际是隐藏而不是重写了
隐藏的话,就没有多态性
楼主应该知道多态性是OO的基本特征之一
不好意思,这个说得有点片面
只有virtual、abstract或override方法可以override
如果只是在子类里加了一个方法,那么当做某个父类处理的时候,在父类里就找不到方法了。
使用Virtual声明成员就保证了这一点,不但父类有处理,子类也可以有处理,使得面向对象的能够很好的被实现了。
踢球A要求:我踢进门就可以
B要求:我一定要用内脚背踢进去
C要求:我一定要用外脚背如果教练没有说明怎么使用内外脚背的踢法,只是教了普通踢法,那么
A就不用自己想办法怎么踢了,只要用教练教的就行
BC就不样了,内外脚背有特殊的技术嘀,所以要自己想办法了
没有virtual或abstract,就没有override!就没有多态性!明白?
==================
1。
LZ 这里, 你的思路取道错了,应该这样理解,只有加了 virtual 修饰符的才可以被子类重载,
否则,不可以。即,virtual 告诉编译器,我要实现多态的功能,如果不加,编译器认为你要定义一个心的方法,覆盖基类方法,csc 会给你一个警告,要你显示使用 new 修饰符
2。程序语言设计里面有两种东东,语法与语义,知道不?编译器即根据语言的设计者定义的 语法与语义 规则, 来翻译你的代码,翻译/解释成机器语言就比如说,我们中文习惯顺序, 英语喜欢倒序,一样virtual/override 这是 C# 实现多态重载的规则,假如方法、属性没有这个修饰符,根据预定义规范,编译器不当你正确的重载方式,甚至无法编译通过。3。
你问它有没有存在的必要?没有人能给你答案,关键字 virtual 是 C# 延续 C++ 的风格, Java 是 C++/C# 的近亲,它就没有整个关键字,在 Java 中,任何方法都可以被子类重载,
但,
C#, 你必须加上 virtual 才可以被子类重载,否则,我不实现 多态 功能4。
你问没有 virtual 是否可以达到同样的功能?可以啊,人家 Java 不就实现了,可是假如你深入的了解,就会发现,他们的实现方式还是有区别的,
那么,我们作为语言的消费者,使用上肯定也有区别,
到底什么区别, 自己你实践才能体会,
也就是说,override的方法归根到底基类必须是虚方法!
但virtual方法未必是abstract的
abstract的方法只能在abstract类中出现
而实际上有大量非抽象类,难道就不能实现多态?
B要求:我一定要用内脚背踢进去
C要求:我一定要用外脚背如果教练没有说明怎么使用内外脚背的踢法,只是教了普通踢法,那么
A就不用自己想办法怎么踢了,只要用教练教的就行
BC就不样了,内外脚背有特殊的技术嘀,所以要自己想办法了
语言如果没有 virtual/abstract/override 是不是可以实现多态??答案是肯定的!!!!!!!!!!!!!!!!!!!!!!!!!C# 有 virtual/abstract/overrideC++ 只有 virtualJava 只有 abstract
他们不都实现了 多态 嘛???????
LZ 你完全可以设计一种语言,
不用上面三个的任何关键字,
完全也可以实现多态功能,
但是你得有足够的功底,足够的数学功底Understand??????????????????????????????
{
InitializeComponent();
base.OnInit(e);
}
多态性,编译时的多态性是通过重载(overload)来实现,运行时的多态性是通覆写(override)虚成员实现
而虚拟方法和覆写(override)是实现运行时的多态性我收藏了一篇文章,您看看,应该会有所帮助。学习是一点一点的,不要急我先找找。
http://blog.csdn.net/love610/archive/2006/02/06/593203.aspx例子比较简单,易懂很。日后,代码写多了,就会更多的理解它。
首先,我为我的言语,让你感到不安致以最诚意的歉意!!!I'm so sorry!我没有歧视任何人,不也会歧视任何人,我是最近一个月才泡上CSDN的。
我说过,我专业非CS,你可以想象,我走的路,不会比你平坦,几乎每个人都是这样过来的。2。
我不是高手,至多比你多写了几行代码,多看点资料而已,我非计算机科班出身,我是搞机械的,虽然现在连丁字尺都不懂得卡了^_^,3。
我很应该高兴,看到大家的踊跃拍砖,
每个人都会肯定,敢于提问的朋友。4。
今天心情实在有点糟,令大家不愉快了,实在抱歉。
Good Luck!
protected override void InitializeCulture()
{
}
当改变皮肤的时候
protected override void OnPreInit(EventArgs e)
{}
一个事件就执行那么一个事,可以慢慢试试
当然想弄明白是件好事
个人肤浅的认为
Virtual去重写
就好比,父亲有吃饭的方法,儿子也有
儿子和父亲是继承的关系,
但是吃饭的方式方法又不同,难道你用程序模拟这个现象的时候,儿子就不叫‘吃饭’了么
都应该叫Eating,所以,你要去重写父亲的方法,因为你们是继承关系
其实是不和逻辑的
抽象的现实,就是父亲是Eating
那你就是别的什么什么ing
不和逻辑吧
所以,我们要常常把自己的程序放在现实,看看能不能说通就对了
面向对象么
才明白的
呵呵
LZ Good Luck
结贴。
using System;
class TestClass
{
public class Dimensions
{
public const double PI = Math.PI;
protected double x, y;
public Dimensions()
{
}
public Dimensions(double x, double y)
{
this.x = x;
this.y = y;
} public virtual double Area()
{
return x * y;
}
} public class Circle : Dimensions
{
public Circle(double r)
: base(r, 0)
{
} public override double Area()
{
return PI * x * x;
}
} class Sphere : Dimensions
{
public Sphere(double r)
: base(r, 0)
{
} public override double Area()
{
return 4 * PI * x * x;
}
} class Cylinder : Dimensions
{
public Cylinder(double r, double h)
: base(r, h)
{
} public override double Area()
{
return 2 * PI * x * x + 2 * PI * x * y;
}
} static void Main()
{
double r = 3.0, h = 5.0;
Dimensions c = new Circle(r);
Dimensions s = new Sphere(r);
Dimensions l = new Cylinder(r, h);
// Display results:
Console.WriteLine("Area of Circle = {0:F2}", c.Area());
Console.WriteLine("Area of Sphere = {0:F2}", s.Area());
Console.WriteLine("Area of Cylinder = {0:F2}", l.Area());
}
}
了解何时使用 Override 和 New 关键字(C# 编程指南)
请参见
全部折叠 全部展开 语言筛选器: 全部 语言筛选器: 多个 语言筛选器: Visual Basic 语言筛选器: C# 语言筛选器: C++ 语言筛选器: J# 语言筛选器: JScript
Visual Basic(声明)
Visual Basic(用法)
C#
C++
J#
JScript C# 允许派生类中的方法与基类中的方法具有相同的名称,只要您非常明确应如何处理新方法。下面的示例演示 new 和 override 关键字的使用。首先声明三个类:一个名为 Car 的基类以及从该基类派生的两个类 ConvertibleCar 和 Minivan。基类包含一个可将有关汽车的描述发送到控制台的方法 (DescribeCar)。派生类方法也包含一个名为 DescribeCar 的方法,该方法显示派生类的独特属性。这些方法还调用基类的 DescribeCar 方法来演示从 Car 类继承属性的方式。 为了强调区别,ConvertibleCar 类使用 new 关键字来定义,而 Minivan 类使用 override 来定义。C# 复制代码
// Define the base class
class Car
{
public virtual void DescribeCar()
{
System.Console.WriteLine("Four wheels and an engine.");
}
}// Define the derived classes
class ConvertibleCar : Car
{
public new virtual void DescribeCar()
{
base.DescribeCar();
System.Console.WriteLine("A roof that opens up.");
}
}class Minivan : Car
{
public override void DescribeCar()
{
base.DescribeCar();
System.Console.WriteLine("Carries seven people.");
}
} 现在可以编写一些代码来声明这些类的实例,并调用它们的方法以便对象能够描述其自身:C# 复制代码
public static void TestCars1()
{
Car car1 = new Car();
car1.DescribeCar();
System.Console.WriteLine("----------"); ConvertibleCar car2 = new ConvertibleCar();
car2.DescribeCar();
System.Console.WriteLine("----------"); Minivan car3 = new Minivan();
car3.DescribeCar();
System.Console.WriteLine("----------");
} 正如预期的那样,输出类似如下所示:Four wheels and an engine. ---------- Four wheels and an engine. A roof that opens up. ---------- Four wheels and an engine. Carries seven people. ---------- 但是,在该代码接下来的一节中,我们声明了一个从 Car 基类派生的对象的数组。此数组能够存储 Car、ConvertibleCar 和 Minivan 对象。该数组的声明类似如下所示:C# 复制代码
public static void TestCars2()
{
Car[] cars = new Car[3];
cars[0] = new Car();
cars[1] = new ConvertibleCar();
cars[2] = new Minivan();
} 然后可以使用一个 foreach 循环来访问该数组中包含的每个 Car 对象,并调用 DescribeCar 方法,如下所示:C# 复制代码
foreach (Car vehicle in cars)
{
System.Console.WriteLine("Car object: " + vehicle.GetType());
vehicle.DescribeCar();
System.Console.WriteLine("----------");
} 此循环的输出如下所示:Car object: YourApplication.Car Four wheels and an engine. ---------- Car object: YourApplication.ConvertibleCar Four wheels and an engine. ---------- Car object: YourApplication.Minivan Four wheels and an engine. Carries seven people. ---------- 注意,ConvertibleCar 说明与您的预期不同。由于使用了 new 关键字来定义此方法,所调用的不是派生类方法,而是基类方法。Minivan 对象正确地调用重写方法,并产生预期的结果。若要强制一个规则,要求从 Car 派生的所有类都必须实现 DescribeCar 方法,则应创建一个新的基类,将方法 DescribeCar 定义为 abstract。抽象方法不包含任何代码,仅包含方法签名。从此基类派生的任何类都必须提供 DescribeCar 的实现。有关更多信息,请参见抽象。请参见
参考
对象、类和结构(C# 编程指南)概念
C# 编程指南
使用 Override 和 New 关键字控制版本(C# 编程指南)
要提出有关“帮助”或本产品其他功能的建议或错误报告,请转到反馈站点。
写了个父类A,里边有方法b(b方法并没有加virtual)
子类继承A 后 写了个同样的方法b 楼主的疑问可能是 我在子类同样可以重写父类的b方法,为什么还有virtual存在的必要?
如果楼主的问题是这样的话,我说说我的理解
我上边的那种写法并不叫重写,专业点的话叫做 我在子类中隐藏了父类的B成员而重写方法,必须要加override申明,而如果父类方法没有申明为可重写,那么在编译时就会报错(无法重写)如果你质疑 ”重写“存在的必要,请去看看多态方面的资料
{
public:
HERE_IS_FOR_virtual void aa(){ MessageBox("是 A 类把我输出来的");
}class B: A
{
public:
void aa(){ MessageBox("是 B 类把我输出来的");
void bb(){ a();};
void bbbb(){ A::aa();}
}void A_function(void)
{
A a;
B b;
a.aa(); //"是 A 类把我输出来的"
b.aa(); //"是 B 类把我输出来的"
b.bb(); //"是 A 类把我输出来的"
b.bbbb(); //"是 A 类把我输出来的"
}
在A_function中,aa()是直接call by reference, compiler 知道得非常清楚,没有ambiguity。但是, 有除了直接call by reference, C++语言中,还可以call by pointer。void B_function(A* pa)
{
pa->aa();
}
在 B_function 中, pa 可以是A*, 也可以是(A*)B*, 这是完全合乎语法的。 在(A*)B*这种情况下, 如果在class A 中, HERE_IS_FOR_virtual 换成 virtual, 把aa()声明成virtual function, 那么, pa->aa() call的是 class B 的aa(), 输出"是 B 类把我输出来的", 如果HERE_IS_FOR_virtual换成空气, 也就是aa()不是virtual, 那么pa->aa() call的是 class A 的aa(), 输出"是 A 类把我输出来的"。在A_function中, 有没有virtual都一样, 在B_function中, 天差地别, virtual function 在 B_function 中的用法就是 Polymophism
{
public:
void aa(){ MessageBox("是 B 类把我输出来的");
void bb(){ a();}; ----->更正为, void bb(){ aa();};
void bbbb(){ A::aa();}
}void A_function(void)
{
A a;
B b;
a.aa(); //"是 A 类把我输出来的"
b.aa(); //"是 B 类把我输出来的"
b.bb(); //"是 A 类把我输出来的" ---->更正为 "是 B 类把我输出来的"
b.bbbb(); //"是 A 类把我输出来的"
}特此 DEBUG , 结帖
{
Person[] per = new Person[5]; Chinese cn1 = new Chinese();
Chinese cn2 = new Chinese();
Japanese jp1 = new Japanese();
Japanese jp2 = new Japanese();
Beijing bj1 = new Beijing();
per[0] = cn1;
per[1] = cn2;
per[2] = jp1;
per[3] = jp2;
per[4] = bj1; // Chinese[]={}
// Japanese[]={};
for (int i = 0; i < per.Length; i++)
{
//if (per[i] is Chinese)
//{
// Chinese c = per[i] as Chinese;
// c.ShowNationality();
//}
//else if (per[i] is Japanese)
//{
// Japanese j = (Japanese)per[i];
// j.ShowNationality();
//}if per[i].ShowNationality();
} //Person p = new Chinese();
//Chinese p = new Chinese();
//p.go();
Console.ReadKey();
}
}
//class Person
//{
// public string Name
// {
// get;
// set;
// } // public int Age
// {
// get;
// set;
// } // //
// virtual public void ShowNationality()
// { // } //} //class Chinese : Person
//{
// public string HuKou
// {
// get;
// set;
// } // //显示国籍
// public override void ShowNationality()
// {
// base.ShowNationality();
// // Console.WriteLine("中国");
// }
//} //class Japanese : Person
//{
// public void PoFu()
// {
// Console.WriteLine("各种颜色!");
// } // public override void ShowNationality()
// {
// Console.WriteLine("日ben!");
// }
//}
//以下是关于抽象方法与抽象类
abstract class Person
{
public string Name
{
get;
set;
} public int Age
{
get;
set;
}
public void sayHello()
{
Console.WriteLine("Hi,everybody!");
}
//抽象放
virtual public void ShowNationality() { } virtual public void test()
{
} virtual public void go()
{
Console.WriteLine("go somewhere");
} } class Chinese : Person
{
public string HuKou
{
get;
set;
} public new void go()
{
Console.WriteLine("go 饶平!");
}
//显示国籍
public new void ShowNationality()
{
//base.ShowNationality();//抽象类不能实例化,所以不能通过base来调用。
Console.WriteLine("中国");
//this.sayHello();
}
} class Japanese : Person
{
public void PoFu()
{
Console.WriteLine("各种颜色!");
} public override void ShowNationality()
{
Console.WriteLine("日ben!");
}
} class Beijing : Chinese
{ public new void ShowNationality()
{
Console.WriteLine("我是很牛13的北京人!");
} }
}