虚函数与纯虚函数

http://blog.sina.com.cn/s/blog_624ca8080100f7th.html

1、基本形式:
virtual ReturnType Function_1();            //虚函数声明
virtual ReturnType Function_2() = 0;      //纯虚函数声明
先讲示例吧,再总结结论。

2、示例:
class Animail{
public:
    void Function_1() {cout <<"Animail::Function_1()"<<endl;};
};

class Dog: public Animail{
 public:
     void Function_1() {cout <<"Dog::Function_1()"<<endl;};
};
int main(int argc, char* argv[])
{
    Animail*p = NULL; //定义基类的指针
    Animail cAnimail;
    Dog cDog;

    p = &cAnimail;
    p->Function_1();

    p =&cDog;
    p->Function_1();
    return 0;
}

这段代码的输出结果是什么呢?起初我认为是:Animail::Function_1()与Dog::Function_1(), 因为第一次输出是引用基类Animail的实例,第二次输出是引用子类Dog的实例。事实上答案是Animail::Function_1()与 Animail::Function_1(),为什么呢?

这里我们需要明白:你就记住,不管引用的实例是哪个类的,当你调用的时候,系统会调用左值那个对象所属类的方法。比如说 上面的代码类Animail和 Dog都有一个Function_1函数,因为p是一个Animail类的指针,所以不管你将p指针指向类Animail或是类Dog,最终调用的函数都是类Animail的Function_1函数。这就是静态联篇,编译器在编译的时候就已经确定好了。可是如果我想实现跟据实例的不同来动态决定调用哪个函数呢?这就须要用到虚函数(也就是动态联篇)。

class Animail{
public:
    virtual void Function_1() {cout <<"Animail::Function_1()"<<endl;};
};

class Dog: public Animail{
 public:
     virtual void Function_1() {cout <<"Dog::Function_1()"<<endl;};
};

在基类的成员函数前加关键字virtual,则表示这个函数是一个虚函数。
所谓虚函数就是在编译的时候不确定要调用哪个函数,而是动态决定将要调用哪个函数。它的作用就是为了能让这个函数在它的子类里面可以被重载,这样的话,编译器就可以使用后期绑定来达到多态了,也就是:用基类的指针来调用子类的这个函数。
要实现虚函数必须保证派生类的函数名与基类相同,参数名参数类型等也要与基类相同。但派生类中的virtual关键字可以省略,也表示这是一个虚函数。
下面来分析一下代码,声明一个基类的指针(必须是基类,反之则不行)p,把p指向类Animail的实例cAnimail,调用Function_1函数,这时系统会判断p所指向的实例的类型,如果是Animail类的实例就调用Animail类的Function_1函数,如果是Dog类的实例cDog就调用Dog类的Function_1函数。

下面来讲一下纯虚函数,包含纯虚函数的类也可叫虚基类或者抽象类
class Animail{
public:
    virtual void GetColor()  = 0;
};

class Dog : public Animail{
 public:
     virtual void GetColor() {cout <<"Yellow"endl;};
};

class Pig : public Animail{
public:
 virtual void GetColor() {cout <<"White"<<endl;};
};

如上代码,定义了一个动物类(Animail),类中有一函数GetColor可取得动物颜色,但动物有很多很多种,颜色自然无法确定,所以就把它声明为纯虚函数,也就是光声明函数名不去定义(实现)它,类Dog继承了Animail并实现了里面的代码,返回黄色。Bike类同样道理。有一点须要注意一下,纯虚函数不能实例化,但可以声明指针,所以上面的main函数中: Animail cAnimail; 编译器会告诉你:由于它的成员的原因,无法instantiate 抽象类Animail,并且警告你GetColor() 没有定义。

虚函数
    1, 虚函数是非静态的、非内联的成员函数。
    2, 若类中一个成员函数被说明为虚函数,则该成员函数在派生类中可能有不同的实现。当使用该成员函数操作指针或引用所标识的对象时,对该成员函数调用可采用动态联编。
    5, 定义了虚函数后,程序中声明的指向基类的指针就可以指向其派生类。在执行过程中,该函数可以不断改变它所指向的对象,调用不同版本的成员函数,而且这些动作都是在运行时动态实现的。虚函数充分体现了面向对象程序设计的动态多态性。虚函数充分体现了面向对象程序设计的动态多态性。

纯虚函数
    1, 当在基类中不能为虚函数给出一个有意义的实现时,可以将其声明为纯虚函数,其实现留待派生类完成。
    2, 纯虚函数的作用是为派生类提供一个一致的接口,它只是个函数的声明而已,它告诉编译器,在这个类中的这个纯虚函数是没有函数定义的,该类不能创建对象(即不能实例化),但可以声明指针,该类的派生类负责给出这个虚函数的重载定义。

原文地址:https://www.cnblogs.com/chengxuyuandashu/p/3970433.html