一、C++中
1、虚函数(virtual)
第一次引入虚拟函数的基类时,必须在类声明中指定virtual关键字。如果虚函数的定义放在类的外面,则不能再次指定关键字virtual。假设有下面的类层次:
class A
{
public:
virtual void foo() { cout << "A::foo() is called" << endl;}//定义一个虚函数
};
class B: public A
{
public:
//备注:只要在基类中已声明为virtual,这里即使不使用virtual关键字,默认也是虚函数
//同样,如果还有从B派生的子类,对应的成员函数也是虚函数
virtual void foo() { cout << "B::foo() is called" << endl;}
};
//那么,在使用的时候,我们可以:
A * a = new B();
a->foo();// 在这里,a虽然是指向A的指针,但是被调用的函数(foo)却是B的!
这个例子是虚函数的一个典型应用。所谓虚函数,虚就虚在“推迟联编”或者“动态联编”上,一个类函数的调用并不是在编译时刻被确定的,而是在运行时刻被确定的。由于编写代码的时候并不能确定被调用的是基类的函数还是哪个派生类的函数,所以被称为“虚”函数。
2、纯虚函数
它是一种特殊的虚函数,它的一般格式如下:
class <类名>
{
virtual <类型><函数名>(<参数表>)=0;
…
};
在许多情况下,在基类中不能对虚函数给出有意义有实现,而把它说明为纯虚函数,它的实现留给该基类的派生类去做。这就是纯虚函数的作用。
3抽象类
(1)带有纯虚函数的类称为抽象类。
(2)抽象类是一种特殊的类,它是为了抽象和设计的目的而建立的,它处于继承层次结构的较上层。
(3)抽象类是不能实例化对象的,在实际中为了强调一个类是抽象类,可将该类的构造函数说明为保护的访问控制权限。
(4)抽象类的主要作用是将有关的组织在一个继承层次结构中,由它来为它们提供一个公共的根,相关的子类是从这个根派生出来的。
二、C#
1、虚函数
(1)若一个实例方法声明前带有virtual关键字,那么这个方法就是虚函数。
(2)虚方法前不允许有static,abstract,或override修饰符
(3)虚方法不能是私有的,因此不能使用private修饰符
class A
{
public virtual void Sum() //虚函数
{
("I am AClass,I am virtual sum().");
}
}
class B : A
{
public override void Sum() //重新实现了虚函数(重写)
{
("I am BClass,I am override sum().");
}
}
class Program
{
static void Main(string[] args)
{
A a = new B(); //定义一个a这个A类的对象.这个A就是a的申明类,实例化a对象,B是a的实例类
();
();
}
}
2抽象函数(等同于C++中的纯虚函数)
(1)抽象函数没有执行代码,必须在非抽象的派生类中重写
(2)抽象函数是虚拟的,但不需要提供virtual关键字,否则会报错
abstract class Building
{
public abstract decimal CalculateHeatingCost(); // abstract method
}
3抽象类
(1)使用关键字abstract声明的类为抽象类
abstract class MyAbs
{
public void NonAbMethod()
{
("Non-Abstract Method");
}
}
(2)抽象类不能直接实例化(java中也是)
(3)抽象类中可以包含抽象成员,但是非抽象类中可不行,即如果类包含抽象函受,该类将也是抽象的,也必须声明为抽象的
(4)不能把关键字abstract 和sealed 一起用在C#中,因为一个密封类不能够被抽象
三、三者概念的对比
|
虚函数 |
纯虚函数 |
抽象类 |
C++ |
由virtual声明 |
virtual <类型><函数名>(<参数表>)=0; |
只要包含纯虚函数的类 |
C# |
由virtual声明 |
abstract <类型><函数名>(<参数表>) |
用abstract声明的类 |