在 C++ 中免不了學到物件導向,其中 virtual function 是其中一個小概念。
虛擬函式 Virtual Function
首先要理解 Base 是父類,被 Derived 子類繼承 Base。
當我們宣告 virtual function 後,若有繼承的 class 的話,這個函式可以被重新定義。像是下方 func1() 和 func2() 都可以覆寫,若沒有覆寫的話就是以父類為主。(不強制子類實作)
class Base {
public:
virtual void func1() {}
virtual void func2() {}
void nonVirtualfunc() {}
};
class Derived : public Base {
public:
virtual void func2() override {}
void nonVirtualfunc() {}
};
Base testBase;
Derived testDerived;
實際例子可看下方:
# include <iostream>
# include <vector>
using namespace std;
class Animal {
public:
virtual void intro() {
cout << "Animal: I am Animal." << endl;
}
virtual ~Animal() {}
};
class Wolf : public Animal {
public:
virtual void intro() override {
cout << "Wolf: I am Wolf." << endl;
}
};
class Dog : public Animal {
public:
virtual void intro() override {
cout << "Dog: I am Dog." << endl;
}
};
class OtherAnimal : public Animal {};
int main() {
vector<Animal*> animals;
animals.push_back(new Animal());
animals.push_back(new Wolf());
animals.push_back(new Dog());
animals.push_back( new OtherAnimal() );
for(vector<Animal*>::const_iterator it = animals.begin(); it != animals.end(); it++) {
(*it)->intro();
delete *it;
}
return 0;
}
Ouput
Animal: I am Animal.
Wolf: I am Wolf.
Dog: I am Dog.
Animal: I am Animal.
而如果將virtual void intro() { cout << "Animal: I am Animal." << endl; }
改為void intro() const { cout << "Animal: I am Animal." << endl; }
output 就會變成:
Animal: I am Animal.
Animal: I am Animal.
Animal: I am Animal.
Animal: I am Animal.
如果以網頁設計來講,有點像是預設版型和指定版型。如果網頁頁面沒有指定版型,那排版就會是預設的,像是 Animal,如果有指定,那就照指定的去覆蓋。但若是沒有開放客製,像是沒有宣告為虛擬函式的話,那就全部都是預設。
純虛函式 Pure Virtual Function
直接看以下例子,寫法就類似 virtual void func1() = 0,並沒有實作。也就是說 Base 它是抽象類別,不能被實體化,這樣表示子類一定要實作。
class Base {
public:
virtual void func1() = 0;
};
class Derived : public Base {
public:
virtual void func1() override {
cout << "Derived func1\n";
}
};
像是下方程式碼,OtherAnimal 沒有實作,結果噴出錯誤:error: cannot declare variable ‘otherAnimal_a’ to be of abstract type ‘OtherAnimal’
#include <iostream>
using namespace std;
class Animal {
public:
virtual void intro() = 0;
};
class Dog : public Animal {
public:
virtual void intro() override {
cout << "Dog: I am Dog." << endl;
}
};
class OtherAnimal : public Animal {};
int main() {
Dog dog_a;
dog_a.intro();
OtherAnimal otherAnimal_a;
otherAnimal_a.intro();
return 0;
}
以網頁的概念來講,有點像是強制每次製作一個頁面一定要選一個版型,沒有預設的版型可套用,所以如果沒有選擇的話,就會噴錯。
那麼我把 OtherAnimal 那段刪掉,改成如下寫法:
#include <iostream>
using namespace std;
class Animal {
public:
virtual void intro() = 0;
};
class Wolf : public Animal {
public:
virtual void intro() override {
cout << "Wolf: I am Wolf." << endl;
}
};
class Dog : public Animal {
public:
virtual void intro() override {
cout << "Dog: I am Dog." << endl;
}
};
int main() {
Dog dog_a;
dog_a.intro();
Wolf wolf_a;
wolf_a.intro();
Animal *animal_a = new Dog();
animal_a->intro();
return 0;
}
Output
Dog: I am Dog.
Wolf: I am Wolf.
Dog: I am Dog.
這裡就先簡單紀錄一下,之後若有更深層的理解會再更新或是新增篇章。








