关于c#中虚函数和隐藏函数的问题 100
你好大神们,我阅读了教材,加上上网百度了一些东西。但是还是很不理解。(另外大神请顺便看一下括号内我的问题,我还是没有理解那些描述是什么意思。)在我看的教材里面对于重写,隐...
你好大神们,我阅读了教材,加上上网百度了一些东西。但是还是很不理解。(另外大神请顺便看一下括号内我的问题,我还是没有理解那些描述是什么意思。)
在我看的教材里面对于重写,隐藏等的介绍是这样的:
4.2.1 虚方法
把一个基类函数声明为virtual,该函数就可以在派生类中重写了。C#中虚函数的概念与标准的OOP概念相同,可以再派生类中重写虚函数。在调用方法时,会调用对象类型的合适方法
(这句话到底是什么意思啊,什么叫对象类型的合适方法?)。
在函数中,函数不是虚拟的,可以显式地声明为virtual。C#的语法与C++不同,因为C#要求在派生类的函数重写一个函数时,要使用override关键字显式声明。
方法重写的语法避免了C++中很容易发生的潜在运行错误,当派生类的方法签名无意中与基类版本的略有差别时,派生类方法就不能重写基类方法了(这个无意中的差别指的是在方法名称和参数的型号或者别的方面的差别么?这里面所谓“派生类方法就不能重写基类方法了”,指的是在c++中如果出现了这些差别,那么由于没有使用override声明,系统不会检测出你没有重写那个virtual函数,然而程序员也没有办法知晓这一点,导致在c++中派生类的重写没有成功,是这个意思吗?)
以上是书上对于虚方法的所有描述。但是我还是没有看出来虚方法到底用来干什么,什么叫做重写。因为在第二个问题中,我没有使用所谓的重写,我输出了实例化的cd1也就是B类的时候,输出的结果就是子类的方法所表示的结果(而且并没有什么因为没有new所写的警告),如果重写指的是,在子类中定义和父类签名一样的方法时,系统会调用子类的那个方法,那么我即使没有用virtual和override,也实现了所谓的重写。那么到底重写是什么意思呢?
我看了网上的资料,在子类的方法里面调用父类的指针什么的,意思难道是,当需要对父类的实例进行子类的方法操作的时候,就需要重写?
以下两种情况到底哪一种需要使用虚函数啊?
(Class1 父类,B 子类,cd 父类实例 cd1 子类实例 fuc(int i)父类子类同时存在的方法,父类输出1,子类输出2)
1、
Class1 cd=new Class1();(实例化一个父类)
B cd1=cd;(将子类的指针指向父类的实例)
Console.WriteLine(cd1.fuc(1));(调用子类下的fuc方法处理一个实际上是父类的实例)
2、
B cd1=new B;(将cd1 实例化为一个B类就是子类)
Class1 cd=cd1;(将一个父类型的对象(cd是一个对象吧?)指针指向子类的cd1实例)
Console.WriteLine(cd.fuc(1));(调用父类下的fuc方法处理一个实际上是子类的实例)
教材中对于隐藏的说明如下:
4.2.2 如果签名相同的方法在基类和派生类里面进行了声明,但该方法没有声明为virtual override,派生类方法就会隐藏基类方法。(也就是说,如果两个签名相同的方法存在于基类和子类中,系统默认子类中的方法是带new的?)
已有的代码不能通过对基类的引用访问这个方法(什么叫做已有的代码?什么叫做不能通过对基类的引用访问这个方法?我前面对基类引用了方法,如果系统默认隐藏基类方法的话,我应该没有办法调用啊,但是我还是输出了结果1(在使用对基类的实例cd的方法时),也就是说系统的隐藏没有发挥作用,这是为什么呢?),因为对基类的早期版本进行编译时会产生一个编译错误。这个问题只会发生在编写的客户机代码上。C#会发出警告,告诉用户在将来的代码上可能会出问题。(什么叫编写的客户机代码?什么叫将来的代码?会出现什么问题?)
用户不应该试图在将来的代码中通过对基类的引用调用这个重复的方法,(但是我成功的调用了基类的这个方法,而没有出现问题)但所有已有的代码仍会正常工作(哪些代码叫做已有代码?正常工作指的是在没有使用new的情况下以什么规则正常工作?)。 展开
在我看的教材里面对于重写,隐藏等的介绍是这样的:
4.2.1 虚方法
把一个基类函数声明为virtual,该函数就可以在派生类中重写了。C#中虚函数的概念与标准的OOP概念相同,可以再派生类中重写虚函数。在调用方法时,会调用对象类型的合适方法
(这句话到底是什么意思啊,什么叫对象类型的合适方法?)。
在函数中,函数不是虚拟的,可以显式地声明为virtual。C#的语法与C++不同,因为C#要求在派生类的函数重写一个函数时,要使用override关键字显式声明。
方法重写的语法避免了C++中很容易发生的潜在运行错误,当派生类的方法签名无意中与基类版本的略有差别时,派生类方法就不能重写基类方法了(这个无意中的差别指的是在方法名称和参数的型号或者别的方面的差别么?这里面所谓“派生类方法就不能重写基类方法了”,指的是在c++中如果出现了这些差别,那么由于没有使用override声明,系统不会检测出你没有重写那个virtual函数,然而程序员也没有办法知晓这一点,导致在c++中派生类的重写没有成功,是这个意思吗?)
以上是书上对于虚方法的所有描述。但是我还是没有看出来虚方法到底用来干什么,什么叫做重写。因为在第二个问题中,我没有使用所谓的重写,我输出了实例化的cd1也就是B类的时候,输出的结果就是子类的方法所表示的结果(而且并没有什么因为没有new所写的警告),如果重写指的是,在子类中定义和父类签名一样的方法时,系统会调用子类的那个方法,那么我即使没有用virtual和override,也实现了所谓的重写。那么到底重写是什么意思呢?
我看了网上的资料,在子类的方法里面调用父类的指针什么的,意思难道是,当需要对父类的实例进行子类的方法操作的时候,就需要重写?
以下两种情况到底哪一种需要使用虚函数啊?
(Class1 父类,B 子类,cd 父类实例 cd1 子类实例 fuc(int i)父类子类同时存在的方法,父类输出1,子类输出2)
1、
Class1 cd=new Class1();(实例化一个父类)
B cd1=cd;(将子类的指针指向父类的实例)
Console.WriteLine(cd1.fuc(1));(调用子类下的fuc方法处理一个实际上是父类的实例)
2、
B cd1=new B;(将cd1 实例化为一个B类就是子类)
Class1 cd=cd1;(将一个父类型的对象(cd是一个对象吧?)指针指向子类的cd1实例)
Console.WriteLine(cd.fuc(1));(调用父类下的fuc方法处理一个实际上是子类的实例)
教材中对于隐藏的说明如下:
4.2.2 如果签名相同的方法在基类和派生类里面进行了声明,但该方法没有声明为virtual override,派生类方法就会隐藏基类方法。(也就是说,如果两个签名相同的方法存在于基类和子类中,系统默认子类中的方法是带new的?)
已有的代码不能通过对基类的引用访问这个方法(什么叫做已有的代码?什么叫做不能通过对基类的引用访问这个方法?我前面对基类引用了方法,如果系统默认隐藏基类方法的话,我应该没有办法调用啊,但是我还是输出了结果1(在使用对基类的实例cd的方法时),也就是说系统的隐藏没有发挥作用,这是为什么呢?),因为对基类的早期版本进行编译时会产生一个编译错误。这个问题只会发生在编写的客户机代码上。C#会发出警告,告诉用户在将来的代码上可能会出问题。(什么叫编写的客户机代码?什么叫将来的代码?会出现什么问题?)
用户不应该试图在将来的代码中通过对基类的引用调用这个重复的方法,(但是我成功的调用了基类的这个方法,而没有出现问题)但所有已有的代码仍会正常工作(哪些代码叫做已有代码?正常工作指的是在没有使用new的情况下以什么规则正常工作?)。 展开
1个回答
展开全部
如果两个签名相同的方法存在于基类和子类中,系统默认子类中的方法是带new的
是的,会调用子类的
虚方法其实跟接口的功能比较接近,就是可以在基类里面只做声明,但是没有方法体,把实现留给子类完成,这是一种对子类的约定。而方法调用时,父类声明的虚方法是不会执行的,只会去子类寻找重写的函数,但是如果想要调用父类的虚方法,只需要在子类里面使用base.Method()就可以了,这样就能重用父类的声明
是的,会调用子类的
虚方法其实跟接口的功能比较接近,就是可以在基类里面只做声明,但是没有方法体,把实现留给子类完成,这是一种对子类的约定。而方法调用时,父类声明的虚方法是不会执行的,只会去子类寻找重写的函数,但是如果想要调用父类的虚方法,只需要在子类里面使用base.Method()就可以了,这样就能重用父类的声明
追问
还是不清楚到底虚方法的使用是哪一种方法,上面说的两种哪种是需要用虚方法的?
追答
使用虚方法的好处就是基类里面只做声明,把实现留给子类完成,跟接口一样增加系统的扩展性。你有这种需求的时候才使用。举一个使用情景例子:你的系统一开始使用的数据库是sqlserver,然后你实现一套访问sqlserver的基类方法,一段时间后项目又成了mysql数据库,你又得去实现一趟访问mysql的基类方法,当然还有很多其他的数据库可能要使用。同时你的项目中其他部分又使用了刚才sqlserver里面的基类方法,如果你换成了mysql,整个项目的代码都需要修改,但是如果你是使用的虚方法,你只需要切换子类为mysql的,项目的其他地方就都不用修改了
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询