天天看點

虛函數和多态多态

多态

公有繼承派生類對象使用基類的方法,如果希望同一種方法派生類和基類的行為是不同的,也即方法的行為取決于調用該方法的對象,這種行為稱為多态。

  • 基類使用虛方法(此時派生類自動成為虛方法,可以指出也可以不指出)。
  • 基類不使用虛方法,在派生類直接重定義該方法。

聲明為virtual

如果不将函數聲明為virtual,程式将根據引用類型或者指針類型選擇方法。如果聲明為virtual,程式将根據引用或者指針指向對象本身的類型來選擇方法。

舉例來說

基類中方法和析構函數均不聲明為virtual的情況

#include <iostream>
#include <memory>
using namespace std;

class Base
{
public:
    Base() { cout << "created Base\n"; }
    void function() { cout << "this is Base's function" << endl; }
    ~Base(){cout << "this is Base's destroy" << endl;}
};

class Derived : public Base
{
public:
    Derived(){ cout << "created derived" << endl;}
    void function(){cout << "this is Derived's function" << endl;}
    ~Derived(){cout << "this is Derived's destroy" << endl;}
};

int main()
{
    Base* ptr = new Derived;
    // std::unique_ptr<Base> ptr(new Derived);

    ptr->function();
    delete ptr; // delete 語句的根本含義在于調用其析構函數,并釋放記憶體

    return 0;
}
           

輸出

created Base
created derived          可以看出構造函數不受影響,被執行了
this is Base's function                雖然對象是派生類,但是由于指針是指向基類的,是以執行了基類的方法
this is Base's destroy                 雖然對象是派生類,但由于指針是指向基類的,是以隻執行了基類的析構函數,是以該對象未被完全釋放。
           

基類中方法與析構函數均聲明為virtual的情況

#include <iostream>
#include <memory>
using namespace std;

class Base
{
public:
    Base() { cout << "created Base\n"; }
    virtual void function() { cout << "this is Base's function" << endl; }
    virtual ~Base(){cout << "this is Base's destroy" << endl;}
};

class Derived : public Base
{
public:
    Derived(){ cout << "created derived" << endl;}
    void function(){cout << "this is Derived's function" << endl;}
    ~Derived(){cout << "this is Derived's destroy" << endl;}
};

int main()
{
    Base* ptr = new Derived;
    // std::unique_ptr<Base> ptr(new Derived);

    ptr->function();
    delete ptr; // delete 語句的根本含義在于調用其析構函數,并釋放記憶體

    return 0;
}
           

輸出

created Base
created derived
this is Derived's function      執行的是派生類的方法,雖然指針指向的是基類
this is Derived's destroy       析構函數也被正确調用了,
this is Base's destroy
           

其他說明

若方法是通過對象(而不是指針或者引用調用的),則沒有虛方法特性!

繼續閱讀