Mor*_*man 1526 oop programming-languages virtual-functions abstract
抽象函数和虚函数有什么区别?在哪些情况下建议使用虚拟或抽象?哪一个是最好的方法?
BFr*_*ree 2655
抽象函数不具备功能.你基本上是在说,任何一个子类必须给出他们自己的这个方法的版本,但是它太普遍甚至不能尝试在父类中实现.
一个虚函数,基本上就是说看,这里的功能对于子类来说可能是也可能不够好.因此,如果它足够好,请使用此方法,如果没有,则覆盖我,并提供您自己的功能.
Jos*_*rke 289
抽象函数没有实现,只能在抽象类上声明.这会强制派生类提供实现.虚函数提供默认实现,它可以存在于抽象类或非抽象类中.例如:
public abstract class myBase
{
//If you derive from this class you must implement this method. notice we have no method body here either
public abstract void YouMustImplement();
//If you derive from this class you can change the behavior but are not required to
public virtual void YouCanOverride()
{
}
}
public class MyBase
{
//This will not compile because you cannot have an abstract method in a non-abstract class
public abstract void YouMustImplement();
}
Run Code Online (Sandbox Code Playgroud)
Meh*_*ari 78
abstract班级才能拥有abstract会员.abstract类从继承abstract类必须 override的abstract成员.abstract成员是隐式virtual.abstract成员不能提供任何实现(abstract被称为pure virtual在某些语言).小智 35
摘要功能:
虚函数:
Fre*_*els 29
抽象方法:当一个类包含一个抽象方法时,该类必须声明为抽象.抽象方法没有实现,因此,从该抽象类派生的类必须为此抽象方法提供实现.
虚方法:类可以有一个虚方法.虚方法有一个实现.从具有虚方法的类继承时,可以覆盖虚方法并提供其他逻辑,或者将逻辑替换为您自己的实现.
何时使用:在某些情况下,您知道某些类型应该具有特定方法,但是,您不知道此方法应该具有什么实现.
在这种情况下,您可以创建一个包含具有此签名的方法的接口.但是,如果您有这种情况,但是您知道该接口的实现者还将有另一个常用方法(您已经可以为其提供实现),则可以创建一个抽象类.然后,此抽象类包含抽象方法(必须覆盖),以及包含"公共"逻辑的另一种方法.
如果您有一个可以直接使用的类,但是您希望继承者能够更改某些行为,但是它不是必需的,则应该使用虚方法.
BKS*_*eon 28
解释:用类比.希望它会对你有所帮助.
上下文
我在一栋建筑的21楼工作.我对火很偏执.在世界的某个地方,每时每刻都有一场大火烧毁着天空刮板.但幸运的是,我们在这里有一个说明手册,如果发生火灾该怎么办:
火灾逃生()
这基本上是一个名为FireEscape()的虚方法
虚方法
对于99%的情况,这个计划非常好.这是一个有效的基本计划.但是火灾逃生被堵塞或损坏的可能性有1%,在这种情况下,你完全被拧紧,除非你采取一些激烈的行动,否则你会变成烤面包.使用虚拟方法,您可以这样做:您可以使用您自己的计划版本覆盖基本的FireEscape()计划:
换句话说,虚拟方法提供了一个基本计划,如果需要,可以覆盖它.如果程序员认为合适,子类可以覆盖父类的虚方法.
抽象方法
并非所有组织都经过精心培训.有些组织不进行消防演习.他们没有全面的逃避政策.每个人都是为了自己.管理层只对现有的此类政策感兴趣.
换句话说,每个人都被迫开发自己的FireEscape()方法.一个人会走出火灾逃生.另一个人会降落伞.另一个人将使用火箭推进技术飞离建筑物.另一个人会下降.管理层并不关心你如何逃脱,只要你有一个基本的FireEscape()计划 - 如果他们不这样做,你可以保证OHS会像一吨砖一样落在组织上.这就是抽象方法的含义.
两者之间有什么区别?
抽象方法:子类被迫实现自己的FireEscape方法.使用虚拟方法,您有一个等待您的基本计划,但如果不够好,可以选择实施自己的计划.
现在那不是很难吗?
Kam*_*oij 22
抽象方法是必须实现以创建具体类的方法.声明在抽象类中(并且任何具有抽象方法的类必须是抽象类)并且必须在具体类中实现.
虚方法是一种方法,可以使用覆盖在派生类中重写,替换超类中的行为.如果不覆盖,则会获得原始行为.如果你这样做,你总会得到新的行为.这与非虚拟方法相反,不能覆盖但可以隐藏原始方法.这是使用new修饰符完成的.
请参阅以下示例:
public class BaseClass
{
public void SayHello()
{
Console.WriteLine("Hello");
}
public virtual void SayGoodbye()
{
Console.WriteLine("Goodbye");
}
public void HelloGoodbye()
{
this.SayHello();
this.SayGoodbye();
}
}
public class DerivedClass : BaseClass
{
public new void SayHello()
{
Console.WriteLine("Hi There");
}
public override void SayGoodbye()
{
Console.WriteLine("See you later");
}
}
Run Code Online (Sandbox Code Playgroud)
当我实例化DerivedClass并打电话时SayHello,或者SayGoodbye,我得到"Hi There"和"See you later".如果我打电话HelloGoodbye,我会得到"你好"和"以后见".这是因为SayGoodbye是虚拟的,可以用派生类替换.SayHello只是隐藏,所以当我从我的基类调用它时,我得到了我原来的方法.
抽象方法是隐式虚拟的.它们定义必须存在的行为,更像界面.
Meq*_*Net 10
我通过对以下类(从其他答案)进行一些改进使这更简单:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TestOO
{
class Program
{
static void Main(string[] args)
{
BaseClass _base = new BaseClass();
Console.WriteLine("Calling virtual method directly");
_base.SayHello();
Console.WriteLine("Calling single method directly");
_base.SayGoodbye();
DerivedClass _derived = new DerivedClass();
Console.WriteLine("Calling new method from derived class");
_derived.SayHello();
Console.WriteLine("Calling overrided method from derived class");
_derived.SayGoodbye();
DerivedClass2 _derived2 = new DerivedClass2();
Console.WriteLine("Calling new method from derived2 class");
_derived2.SayHello();
Console.WriteLine("Calling overrided method from derived2 class");
_derived2.SayGoodbye();
Console.ReadLine();
}
}
public class BaseClass
{
public void SayHello()
{
Console.WriteLine("Hello\n");
}
public virtual void SayGoodbye()
{
Console.WriteLine("Goodbye\n");
}
public void HelloGoodbye()
{
this.SayHello();
this.SayGoodbye();
}
}
public abstract class AbstractClass
{
public void SayHello()
{
Console.WriteLine("Hello\n");
}
//public virtual void SayGoodbye()
//{
// Console.WriteLine("Goodbye\n");
//}
public abstract void SayGoodbye();
}
public class DerivedClass : BaseClass
{
public new void SayHello()
{
Console.WriteLine("Hi There");
}
public override void SayGoodbye()
{
Console.WriteLine("See you later");
}
}
public class DerivedClass2 : AbstractClass
{
public new void SayHello()
{
Console.WriteLine("Hi There");
}
// We should use the override keyword with abstract types
//public new void SayGoodbye()
//{
// Console.WriteLine("See you later2");
//}
public override void SayGoodbye()
{
Console.WriteLine("See you later");
}
}
}
Run Code Online (Sandbox Code Playgroud)
绑定是将名称映射到代码单元的过程.
后期绑定意味着我们使用名称,但推迟映射.换句话说,我们首先创建/提及名称,然后让一些后续进程处理代码到该名称的映射.
现在考虑:
所以,简短的回答是:virtual是机器的后期绑定指令(运行时),而是abstract人类(程序员)的后期绑定指令
换句话说,virtual意思是:
"亲爱的运行时,通过做你最擅长的事情,将适当的代码绑定到这个名称:搜索 "
鉴于abstract手段:
"亲爱的程序员,请通过做你最擅长的事情将适当的代码绑定到这个名称:发明 "
为了完整起见,重载意味着:
"亲爱的编译器,通过做你最擅长的事情将相应的代码绑定到这个名称:排序 ".