C++中虚函数和纯虚函数的区别与总结
⾸先:强调⼀个概念
定义⼀个函数为虚函数,不代表函数为不被实现的函数。
定义他为虚函数是为了允许⽤基类的指针来调⽤⼦类的这个函数。
定义⼀个函数为纯虚函数,才代表函数没有被实现。
定义纯虚函数是为了实现⼀个接⼝,起到⼀个规范的作⽤,规范继承这个类的程序员必须实现这个函数。
1、简介
假设我们有下⾯的类层次:
class A
{
public:
virtual void foo()
{
cout<<"A::foo() is called"<<endl;
}
};
class B:public A
{
public:
void foo()
{
cout<<"B::foo() is called"<<endl;
}
多态性与虚函数};
int main(void)
{
A *a = new B();
a->foo(); // 在这⾥,a虽然是指向A的指针,但是被调⽤的函数(foo)却是B的!
return 0;
}
这个例⼦是虚函数的⼀个典型应⽤,通过这个例⼦,也许你就对虚函数有了⼀些概念。它虚就虚在所谓“推迟联编”或者“动态联
编”上,⼀个类函数的调⽤并不是在编译时刻被确定的,⽽是在运⾏时刻被确定的。由于编写代码的时候并不能确定被调⽤的是基类的函数还是哪个派⽣类的函数,所以被成为“虚”函数。
虚函数只能借助于指针或者引⽤来达到多态的效果。
C++纯虚函数
⼀、定义
纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派⽣类都要定义⾃⼰的实现⽅法。在基类中实现纯虚函数的⽅法是在函数原型后加“=0”
virtual void funtion1()=0
⼆、引⼊原因
1. 为了⽅便使⽤多态特性,我们常常需要在基类中定义虚拟函数。
2. 在很多情况下,基类本⾝⽣成对象是不合情理的。例如,动物作为⼀个基类可以派⽣出⽼虎、孔雀等⼦类,但动物本⾝⽣成对象明显
不合常理。
为了解决上述问题,引⼊了纯虚函数的概念,将函数定义为纯虚函数(⽅法:virtual ReturnType Funct
ion()= 0;),则编译器要求在派⽣类中必须予以重写以实现多态性。同时含有纯虚拟函数的类称为抽象类,它不能⽣成对象。这样就很好地解决了上述两个问题。
声明了纯虚函数的类是⼀个抽象类。所以,⽤户不能创建类的实例,只能创建它的派⽣类的实例。
纯虚函数最显著的特征是:它们必须在继承类中重新声明函数(不要后⾯的=0,否则该派⽣类也不能实例化),⽽且它们在抽象类中往往没有定义。
定义纯虚函数的⽬的在于,使派⽣类仅仅只是继承函数的接⼝。
纯虚函数的意义,让所有的类对象(主要是派⽣类对象)都可以执⾏纯虚函数的动作,但类⽆法为纯虚函数提供⼀个合理的缺省实现。所以类纯虚函数的声明就是在告诉⼦类的设计者,“你必须提供⼀个纯虚函数的实现,但我不知道你会怎样实现它”。
抽象类的介绍
抽象类是⼀种特殊的类,它是为了抽象和设计的⽬的为建⽴的,它处于继承层次结构的较上层。
(1)抽象类的定义:称带有纯虚函数的类为抽象类。
(2)抽象类的作⽤:
抽象类的主要作⽤是将有关的操作作为结果接⼝组织在⼀个继承层次结构中,由它来为派⽣类提供⼀个公共的根,派⽣类将具体实现在其基类中作为接⼝的操作。所以派⽣类实际上刻画了⼀组⼦类的操作接⼝的通⽤语义,这些语义也传给⼦类,⼦类可以具体实现这些语义,也可以再将这些语义传给⾃⼰的⼦类。
(3)使⽤抽象类时注意:
抽象类只能作为基类来使⽤,其纯虚函数的实现由派⽣类给出。如果派⽣类中没有重新定义纯虚函数,⽽只是继承基类的纯虚函数,则这个派⽣类仍然还是⼀个抽象类。如果派⽣类中给出了基类纯虚函数的实现,则该派⽣类就不再是抽象类了,它是⼀个可以建⽴对象的具体的类。
抽象类是不能定义对象的。
总结:
1. 纯虚函数声明如下: virtual void funtion1()=0; 纯虚函数⼀定没有定义,纯虚函数⽤来规范派⽣类的⾏为,即接⼝。包含纯虚函数的类
是抽象类,抽象类不能定义实例,但可以声明指向实现该抽象类的具体类的指针或引⽤。
2. 虚函数声明如下:virtual ReturnType FunctionName(Parameter);虚函数必须实现,如果不实现,编译器将报错,错误提⽰为:
error LNK****: unresolved external symbol "public: virtual void __thiscall ClassName::virtualFunctionName(void)"
3. 对于虚函数来说,⽗类和⼦类都有各⾃的版本。由多态⽅式调⽤的时候动态绑定。
4. 实现了纯虚函数的⼦类,该纯虚函数在⼦类中就编程了虚函数,⼦类的⼦类即孙⼦类可以覆盖该虚函数,由多态⽅式调⽤的时候动态
绑定。
5. 虚函数是C++中⽤于实现多态(polymorphism)的机制。核⼼理念就是通过基类访问派⽣类定义的函数。
6. 在有动态分配堆上内存的时候,析构函数必须是虚函数,但没有必要是纯虚的。
7. 友元不是成员函数,只有成员函数才可以是虚拟的,因此友元不能是虚拟函数。但可以通过让友元函数调⽤虚拟成员函数来解决友元
的虚拟问题。
8. 析构函数应当是虚函数,将调⽤相应对象类型的析构函数,因此,如果指针指向的是⼦类对象,将调⽤⼦类的析构函数,然后⾃动调
⽤基类的析构函数。
有纯虚函数的类是抽象类,不能⽣成对象,只能派⽣。他派⽣的类的纯虚函数没有被改写,那么,它的派⽣类还是个抽象类。
定义纯虚函数就是为了让基类不可实例化化
因为实例化这样的抽象数据结构本⾝并没有意义。
或者给出实现也没有意义
实际上我个⼈认为纯虚函数的引⼊,是出于两个⽬的
1、为了安全,因为避免任何需要明确但是因为不⼩⼼⽽导致的未知的结果,提醒⼦类去做应做的实现。
2、为了效率,不是程序执⾏的效率,⽽是为了编码的效率。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论