虛函數與多態,函數多態

來源:互聯網
上載者:User

虛函數與多態,函數多態

假設我們有三個類Person、Teacher、Student它們之間的關係如下:



類的關係圖

普通成員函數

【Demo1】
根據這個類圖,我們有下面的代碼實現

#ifndef __OBJEDT_H__#define  __OBJEDT_H__#include <string>#include <iostream>class Person{public:    Person(const string& name, int age) : m_name(name), m_age(age)    {    }    void ShowInfo()    {        cout << "姓名:" << m_name << endl;        cout << "年齡:" << m_age << endl;    }protected:    string  m_name;     //姓名    int     m_age;      //年齡};class Teacher : public Person{public:    Teacher(const string& name, int age, const string& title)        : Person(name, age), m_title(title)    {    }    void ShowInfo()    {        cout << "姓名:" << m_name << endl;        cout << "年齡:" << m_age << endl;        cout << "職稱:" << m_title << endl;    }private:    string  m_title;        //職稱};class Student : public Person{public:    Student(const string& name, int age, int studyId)        : Person(name, age), m_studyId(studyId)    {    }    void ShowInfo()    {        cout << "姓名:" << m_name << endl;        cout << "年齡:" << m_age << endl;        cout << "學號:" << m_studyId << endl;    }private:    int m_studyId;          //學號};#endif  //__OBJEDT_H__

測試代碼:

void test(){    Person* pPerson = new Person("張三", 22);    Teacher* pTeacher = new Teacher("李四", 35, "副教授");    Student* pStudent = new Student("王五", 18, 20151653);    pPerson->ShowInfo();    cout << endl;    pTeacher->ShowInfo();    cout << endl;    pStudent->ShowInfo();    cout << endl;    delete pPerson;    delete pTeacher;    delete pStudent;}

結果:

姓名:張三
年齡:22

姓名:李四
年齡:35
職稱:副教授

姓名:王五
年齡:18
學號:20151653

說明:
這裡的ShowInfo就是一個普通的函數。pPerson、pTeacher和pStudent三個對象調用ShowInfo分別展示自己的資訊。
我們知道:父類的指標是可以指向子類的對象的。我們把上面的測試代碼稍微改一下:
【Demo2】

void test(){    Person* pPerson = new Person("張三", 22);    Person* pTeacher = new Teacher("李四", 35, "副教授");    Person* pStudent = new Student("王五", 18, 20151653);    pPerson->ShowInfo();    cout << endl;    pTeacher->ShowInfo();    cout << endl;    pStudent->ShowInfo();    cout << endl;    delete pPerson;    delete pTeacher;    delete pStudent;}

結果:

姓名:張三
年齡:22

姓名:李四
年齡:35

姓名:王五
年齡:18

這時,pTeacher和pStudent只輸出了姓名和年齡,並沒有輸出子類所具有的特性(職稱和學號)。這應該不是你期望的結果,你可能期望pTeacher和pStudent輸出老師和學生的完整資訊,這時就需要用虛函數。

虛函數

我們把Person中的ShowInfo成員改成虛函數(在前面加上virtual),代碼如下:
【Demo3】

class Person{public:    Person(const string& name, int age) : m_name(name), m_age(age)    {    }    virtual void ShowInfo()    {        cout << "姓名:" << m_name << endl;        cout << "年齡:" << m_age << endl;    }protected:    string  m_name;     //姓名    int     m_age;      //年齡};

在執行上面【Demo2】中的測試代碼,得到我們想到的結果:

姓名:張三
年齡:22

姓名:李四
年齡:35
職稱:副教授

姓名:王五
年齡:18
學號:20151653

虛函數用法要點:

【Demo4】:針對第4點說明:

class Person{public:    Person(const string& name, int age) : m_name(name), m_age(age)    {    }    virtual void ShowInfo()    {        cout << "姓名:" << m_name << endl;        cout << "年齡:" << m_age << endl;    }    string GetName();       //正確,普通函數如果不被使用,可以只有聲明沒有定義    virtual int GetAge();   //錯誤,虛函數必須要有定義,即使是一個空實現,因為編譯器無法確定會使用哪個函數protected:    string  m_name;     //姓名    int     m_age;      //年齡};

【Demo5】:針對第5點進行說明:
設計我們的類如下定義。

class Person{public:    virtual void SetAge(int age = 0)    {        m_age = age;    }    //... 省略};class Teacher : public Person{public:    virtual void SetAge(int age = 1)    {        m_age = age;    }    //... 省略};class Student : public Person{public:    virtual void SetAge(int age = 2)    {        m_age = age;    }    //... 省略};

測試1:

void test(){    Person* pPerson = new Person("張三", 22);    Teacher* pTeacher = new Teacher("李四", 35, "副教授");    Student* pStudent = new Student("王五", 18, 20151653);    pPerson->SetAge();    pTeacher->SetAge();    pStudent->SetAge();    pPerson->ShowInfo();    cout << endl;    pTeacher->ShowInfo();    cout << endl;    pStudent->ShowInfo();    cout << endl;    delete pPerson;    delete pTeacher;    delete pStudent;}

結果:

姓名:張三
年齡:0

姓名:李四
年齡:1
職稱:副教授

姓名:王五
年齡:2
學號:20151653

測試2:

void test(){    Person* pPerson = new Person("張三", 22);    Person* pTeacher = new Teacher("李四", 35, "副教授");    Person* pStudent = new Student("王五", 18, 20151653);    pPerson->SetAge();    pTeacher->SetAge();    pStudent->SetAge();    pPerson->ShowInfo();    cout << endl;    pTeacher->ShowInfo();    cout << endl;    pStudent->ShowInfo();    cout << endl;    delete pPerson;    delete pTeacher;    delete pStudent;}

結果:

姓名:張三
年齡:0

姓名:李四
年齡:0
職稱:副教授

姓名:王五
年齡:0
學號:20151653

純虛函數

在上面的例子中,我們假設所有的人都要工作,但不同的人工作的方式不同。於是我們就要強制要求繼承自Person的子類都要有工作的方法,這就需要純虛函數。定義如下:
【Demo6】

class Person{public:    //... 省略    virtual void DoWork() = 0;        //... 省略};

但此時我們編譯

Person* pPerson = new Person("張三", 22);

這句話時會報錯:error C2259: ‘Person’ : cannot instantiate abstract class
這是因為我們並沒有為Person實現DoWork方法,而包含純虛函數的類是一個抽象的類,抽象類別不能被執行個體化。

於是我們在子類中對它實現如下:
【Demo7】

class Teacher : public Person{public:    //... 省略    virtual void DoWork()    {        cout << "教書..." << endl;    }    //... 省略};class Student : public Person{public:    //... 省略    virtual void DoWork()    {        cout << "學習..." << endl;    }    //... 省略};

沒用DoWork方法:

void test(){    Person* pTeacher = new Teacher("李四", 35, "副教授");    Person* pStudent = new Student("王五", 18, 20151653);    pTeacher->DoWork();    cout << endl;    pStudent->DoWork();    cout << endl;    delete pTeacher;    delete pStudent;}

結果:

教書…

學習…

純虛函數用法要點:

著作權聲明:本文為博主原創文章,未經博主允許不得用於任何商業用途,轉載請註明出處。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.