利用虚函数实现动态多态性

12.3.1 虚函数的作用

能否用同一个调用形式来调用派生类和基类的同名函数。在程序中,不是通过不同的对象名去调用不同派生层次中的同名函数,而是通过指针调用它们。

c++中的虚函数就是用来解决动态多态问题的。所谓虚函数,就是在基类声明函数是虚拟的,并不是实际存在的函数,然后在派生类中才正式定义此函数

下面给出一个例子

#include <iostream>
#include <string>
using namespace std;
const double pi = 3.14;
class student
{
protected:
    int num;
    string name;
    int score;
public:
    student( int nn = 0, string nam = " ", int ss = 0 ):num(nn), name(nam), score(ss) {}
    void display()
    {
        cout << "num: " << num << endl;
        cout << "name: " << name << endl;
        cout << "score: " << score << endl;
    }
};
class Gradstudent:public student
{
protected:
    int wage;
public:
    Gradstudent( int nn = 0, string nam = " ", int ss = 0, int ww = 0 ):student( nn, nam, ss ), wage(ww) {}
    void display()
    {
        cout << "num: " << num << endl;
        cout << "name: " << name << endl;
        cout << "score: " << score << endl;
        cout << "wage: " << wage << endl;
    }
};
int main()
{
    student s1(1, "xutian", 100);
    student *p = &s1;
    p->display();
    Gradstudent s2(2, "zhaoyi", 100, 100000);
    p = &s2;
    p->display();
    return 0;
}

运行结果如下图

程序说明:基类指针是用来指向基类对象的,如果用它指向派生类对象,则自动进行指针类型转换,这样基类指针指向的是派生类对象中的基类部分。

虚函数突破了以上的限制,在基类中的display函数被声明为虚函数。在声明派生类时被重载,这时派生类的同名函数display就取代了其基类中的虚函数。

当把基类的某个成员函数声明为虚函数后,允许在其派生类中对该函数重新定义,赋予它新的功能,并且可以通过指向基类的指针指向同一类族中不同类的对象,从而调用其中的同名函数。

虚函数的使用方法:

(1)在基类中用virtual声明成员函数为虚函数。在类外定义虚函数时,不必再加virtual。

(2)在派生类中重新定义此函数时,函数名、函数类型、函数参数个数和类型必须与基类的虚函数相同,函数体根据派生函数的需要重新定义。

当一个成员函数被定义为虚函数时,其派生类中的同名函数都自动成为虚函数。

(3)定义一个指向基类对象的指针变量,并使它指向同一类族中需要调用该函数的对象。

(4)通过该指针变量调用此函数,此时调用的就是指针变量指向的对象的同名函数。

虚函数处理的是不同派生层次上的同名函数的问题。

修改为虚函数后

#include <iostream>
#include <string>
using namespace std;
const double pi = 3.14;
class student
{
protected:
    int num;
    string name;
    int score;
public:
    student( int nn = 0, string nam = " ", int ss = 0 ):num(nn), name(nam), score(ss) {}
    virtual void display()
    {
        cout << "num: " << num << endl;
        cout << "name: " << name << endl;
        cout << "score: " << score << endl;
    }
};
class Gradstudent:public student
{
protected:
    int wage;
public:
    Gradstudent( int nn = 0, string nam = " ", int ss = 0, int ww = 0 ):student( nn, nam, ss ), wage(ww) {}
    void display()
    {
        cout << "num: " << num << endl;
        cout << "name: " << name << endl;
        cout << "score: " << score << endl;
        cout << "wage: " << wage << endl;
    }
};
int main()
{
    student s1(1, "xutian", 100);
    student *p = &s1;
    p->display();
    Gradstudent s2(2, "zhaoyi", 100, 100000);
    p = &s2;
    p->display();
    return 0;
}
结果如下:

猜你喜欢

转载自blog.csdn.net/xutian_curry/article/details/80483941