虛函數是C++語言中的一個相當重要的概念,特別對於C程序員來說,本身並沒有精力去系統的學習C++中的一些概念,比如虛基類、虛函數等,C++語言不似C語言這般簡潔,紛繁複雜,像是大雜燴,這也是我早期相當討厭C++語言的原因,但是它也有其獨到之處,作爲現代的C程序員,難免會接觸C++,而也是因爲C++語言的繁亂,所以我們學習的時候一定要抓住本質,下面的是我針對C++中虛函數的一些總結,我們將從虛函數的定義、作用功能、應用舉例、實現機制由淺入深的來闡述虛函數,希望在昇華自我的同時也能夠幫助到讀者.........
一、虛函數的定義
虛函數必須爲基類的非靜態函數和非構造函數
其訪問權限可以是protected,當然也可以是public
在基類中定義虛函數的一般形式:virtual 函數返回值類型 虛函數名(形參表){函數體}
特出情況:如果基類中無法實現該函數或者沒有必要實現那麼可以採用純虛函數
純虛函數的形式:virtual 函數返回值類型 虛函數名 = 0 ;
而包含有純虛函數的類我們成爲抽象類。
基類中定義過的虛函數若在派生類中重新定義,那麼是否加virtual修飾就隨你而定
二、虛函數的作用
實現動態聯編(編譯時不知道具體行爲,當運行時纔可確定),
基類中定義了虛函數過後可以在其派生類中重新定義,若沒有重新定義那麼將繼承基類 中的虛函數,但發現函數前virtual之後,系統會自動按照動態聯編來處理,
虛函數也是C++中多態的一種實現,即不同對象傳入相同消息後的不同表現
實現動態聯編一般需要以下三個條件:
1、必須把動態聯編的行爲定義爲類的虛函數。
2、類之間存在子類型關係,一般表現爲 一個類從另一個類公有派生而來。
3、必須先使用基類指針指向子類型的對象,然後直接或者間接使用基類指針調用虛函數
三、應用舉例
#include <stdio.h>
#include <string.h>
class Animal
{
public:
char *name;
Animal(char *name);
virtual ~Animal();
virtual void shout() = 0;
};
Animal::Animal(char *name)
{
this->name = new char[strlen(name)];
strcpy(this->name,name);
}
Animal::~Animal()
{
delete []name;
}
class Dog : public Animal
{
public:
Dog(char *name);
virtual ~Dog();
virtual void shout();
};
Dog::Dog(char *name):Animal(name)
{
this->name = new char[strlen(name)];
strcpy(this->name,name);
}
Dog::~Dog()
{
delete []name;
}
void Dog::shout()
{
printf("Dog shout!!!!\n");
}
class Cat : public Animal
{
public:
Cat(char *name);
virtual ~Cat();
virtual void shout();
};
Cat::Cat(char *name):Animal(name)
{
this->name = new char[strlen(name)];
strcpy(this->name,name);
}
Cat::~Cat()
{
delete []name;
}
void Cat::shout()
{
printf("Cat shout!!!!\n");
}
int main(int argc, char **argv)
{
Animal *dog = new Dog("Dog");
Animal *cat = new Cat("Cat");
dog->shout();
cat->shout();
return 0;
}
一、實現機制
包含或其父類包含虛函數的類都有一個虛表,其對象都會有一個虛指針,該指針指向虛表的首地址:
其中紅色的爲在子類中覆蓋了父類函數,黑色爲沒有覆蓋,注意,C的實例不可以調用e() y(),當C實例化對象時候,就會給它分配一個VPTR指針指向該類的虛表,用父類對象指針指向子類對象,也同樣會調用被子類覆蓋了的函數。