当前位置:  开发笔记 > 编程语言 > 正文

抽象函数和虚函数有什么区别?

如何解决《抽象函数和虚函数有什么区别?》经验,为你挑选了11个好方法。

抽象函数和虚函数有什么区别?在哪些情况下建议使用虚拟或抽象?哪一个是最好的方法?



1> BFree..:

抽象函数不具备功能.你基本上是在说,任何一个子类必须给出他们自己的这个方法的版本,但是它太普遍甚至不能尝试在父类中实现.

一个虚函数,基本上就是说看,这里的功能对于子类来说可能是也可能不够好.因此,如果它足够好,请使用此方法,如果没有,则覆盖我,并提供您自己的功能.


当然,如果你覆盖一个虚方法,你总是可以通过调用base.Foo(...)来引用父方法.
谢谢.这是一个比MSDN文档中的任何内容都要好得多且简单易懂的解释.(阅读五分钟之后我很头疼:http://msdn.microsoft.com/en-us/library/aa645767(v = vs.71) )的.aspx)
这应该在Microsoft参考库中,我花了10分钟阅读并仍然感到困惑.
来自Java,我有点困惑为什么我们需要将它变为虚拟,直到我读到这个:http://stackoverflow.com/a/1062126/193634
@MeqDotNet这意味着如果你喜欢我的实现,请使用我,如果不比我自己写得更好:)
可能值得一提的是,Jake上面提到的关于**虚拟**的令人头疼的MSDN文档来自2003年的文档.以下来自2013年文档的MSDN链接更加简洁:http://msdn.microsoft.com/en-us/library/9fkccyh4.aspx
您还需要将父类标记为抽象类,以强制子类实现所有抽象方法/函数

2> JoshBerke..:

抽象函数没有实现,只能在抽象类上声明.这会强制派生类提供实现.虚函数提供默认实现,它可以存在于抽象类或非抽象类中.例如:

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();
}


查看示例代码非常有用 - 有助于使答案中的各种解释更加清晰.
我回滚了以前版本的答案:这两个类只是示例,第一个类将编译,因为它被标记为抽象,第二个不会.MyBase是否从其他类继承是无关紧要的.
你的`MyBase`类不是必须以某种方式实现**抽象**类吗?我不经常这样做,所以我可能会弄错.在你的例子中我没有看到.
在上面的例子中,MyBase显示了你不能做的事情.也就是说,你不能在非抽象类中使用抽象方法

3> Mehrdad Afsh..:

    只有abstract班级才能拥有abstract会员.

    一个非abstract类从继承abstract必须 overrideabstract成员.

    一个abstract成员是隐式virtual.

    一个abstract成员不能提供任何实现(abstract被称为pure virtual在某些语言).


不,我的意思正是我写的.抽象类的成员可以是"虚拟"或非"虚拟".一个`abstract`成员(即抽象属性,抽象方法)就像一个虚方法,即你可以覆盖它,除了它不带有默认实现.

4> Rinat Abdull..:

您必须始终覆盖抽象函数.

从而:

抽象函数 - 当继承者必须提供自己的实现时

虚拟 - 何时由继承人决定



5> 小智..:

摘要功能:

    它只能在抽象类中声明.

    它只包含方法声明而不是抽象类中的实现.

    必须在派生类中重写它.

虚函数:

    它可以在abstract和non abstract类中声明.

    它包含方法实现.

    它可能被覆盖了.



6> Frederik Ghe..:

抽象方法:当一个类包含一个抽象方法时,该类必须声明为抽象.抽象方法没有实现,因此,从该抽象类派生的类必须为此抽象方法提供实现.

虚方法:类可以有一个虚方法.虚方法有一个实现.从具有虚方法的类继承时,可以覆盖虚方法并提供其他逻辑,或者将逻辑替换为您自己的实现.

何时使用:在某些情况下,您知道某些类型应该具有特定方法,但是,您不知道此方法应该具有什么实现.
在这种情况下,您可以创建一个包含具有此签名的方法的接口.但是,如果您有这种情况,但是您知道该接口的实现者还将有另一个常用方法(您已经可以为其提供实现),则可以创建一个抽象类.然后,此抽象类包含抽象方法(必须覆盖),以及包含"公共"逻辑的另一种方法.

如果您有一个可以直接使用的类,但是您希望继承者能够更改某些行为,但是它不是必需的,则应该使用虚方法.



7> BKSpurgeon..:

解释:用类比.希望它会对你有所帮助.

上下文

我在一栋建筑的21楼工作.我对火很偏执.在世界的某个地方,每时每刻都有一场大火烧毁着天空刮板.但幸运的是,我们在这里有一个说明手册,如果发生火灾该怎么办:

火灾逃生()

    不要收集物品

    走到火灾逃生

    走出建筑物

这基本上是一个名为FireEscape()的虚方法

虚方法

对于99%的情况,这个计划非常好.这是一个有效的基本计划.但是火灾逃生被堵塞或损坏的可能性有1%,在这种情况下,你完全被拧紧,除非你采取一些激烈的行动,否则你会变成烤面包.使用虚拟方法,您可以这样做:您可以使用您自己的计划版本覆盖基本的FireEscape()计划:

    运行到窗口

    跳出窗外

    降落伞安全到底

换句话说,虚拟方法提供了一个基本计划,如果需要,可以覆盖它.如果程序员认为合适,子类可以覆盖父类的虚方法.

抽象方法

并非所有组织都经过精心培训.有些组织不进行消防演习.他们没有全面的逃避政策.每个人都是为了自己.管理层只对现有的此类政策感兴趣.

换句话说,每个人都被迫开发自己的FireEscape()方法.一个人会走出火灾逃生.另一个人会降落伞.另一个人将使用火箭推进技术飞离建筑物.另一个人会下降.管理层并不关心你如何逃脱,只要你有一个基本的FireEscape()计划 - 如果他们不这样做,你可以保证OHS会像一吨砖一样落在组织上.这就是抽象方法的含义.

两者之间有什么区别?

抽象方法:子类被迫实现自己的FireEscape方法.使用虚拟方法,您有一个等待您的基本计划,但如果不够好,可以选择实施自己的计划.

现在那不是很难吗?



8> Kamiel Wanro..:

抽象方法是必须实现以创建具体类的方法.声明在抽象类中(并且任何具有抽象方法的类必须是抽象类)并且必须在具体类中实现.

虚方法是一种方法,可以使用覆盖在派生类中重写,替换超类中的行为.如果不覆盖,则会获得原始行为.如果你这样做,你总会得到新的行为.这与非虚拟方法相反,不能覆盖但可以隐藏原始方法.这是使用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");
    }
}

当我实例化DerivedClass并打电话时SayHello,或者SayGoodbye,我得到"Hi There"和"See you later".如果我打电话HelloGoodbye,我会得到"你好"和"以后见".这是因为SayGoodbye是虚拟的,可以用派生类替换.SayHello只是隐藏,所以当我从我的基类调用它时,我得到了我原来的方法.

抽象方法是隐式虚拟的.它们定义必须存在的行为,更像界面.



9> Rashack..:

抽象方法总是虚拟的.他们无法实施.

这是主要的区别.

基本上,如果您具有虚拟方法,并且希望允许后代更改其行为,则可以使用虚方法.

使用抽象方法,可以强制后代提供实现.



10> MeqDotNet..:

我通过对以下类(从其他答案)进行一些改进使这更简单:

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");
        }
    }
}



11> Rodrick Chap..:

绑定是将名称映射到代码单元的过程.

后期绑定意味着我们使用名称,但推迟映射.换句话说,我们首先创建/提及名称,然后让一些后续进程处理代码到该名称的映射.

现在考虑:

与人类相比,机器非常擅长搜索和排序

与机器相比,人类在发明和创新方面非常擅长

所以,简短的回答是:virtual是机器的后期绑定指令(运行时),而是abstract人类(程序员)的后期绑定指令

换句话说,virtual意思是:

"亲爱的运行时,通过做你最擅长的事情,将适当的代码绑定到这个名称:搜索 "

鉴于abstract手段:

"亲爱的程序员,请通过做你最擅长的事情将适当的代码绑定到这个名称:发明 "

为了完整起见,重载意味着:

"亲爱的编译器,通过做你最擅长的事情将相应的代码绑定到这个名称:排序 ".

推荐阅读
重庆制造漫画社
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有