一、抽象類學習筆記
1.virtual修飾函數(虛函數)后面加=0就稱為一個純虛函數,一個類中只要有純虛函數那么它就是一個抽象類。抽象類不能用來實例化對象,是用來給他的派生類定義好這些框架的,給使用這個類的程序定義好接口。
2.抽象類中可以部分是純虛函數,部分是實現好的函數。
3.若派生類沒有全部實現父類的存純虛函數,由於繼承關系,子類中也會有純虛函數,因此子類也是抽象類,不能實例化對象。
4.多態中的兩個特例在純虛函數中是不成立的。(各自返回本對象的指針或引用、析構函數前加virtual)
5.實現為抽象類的好處:編寫簡單,可以防止適用此類來實例化對象。
6.抽象類界面
一個程序由多人合作編寫,類編程和應用編程,目的是修改類重新生成庫,但是應用程序不需要重新編譯。
類編程:提供的類生成動態庫
應用編程:使用動態庫實現邏輯
例子中應用程序包含各個庫的頭文件,修改頭文件就不行了,運行后程序崩潰了。
實現應用程序不包含類的頭文件:
app
-------------------------------------
Human.h
-------------------------------------
Englishman Chineseman
使用這項技術把容易變化的類和應用程序隔離開了,中間引入一個相對固定的Human.h,它是一個接口是抽象類的界面。應用編程和類編程區分開來,互不影響。
7.析構函數可以定義為虛函數以達到在父類指針或引用在消除時調用子類的析構函數(然后再調用父類的析構函數)。但是析構函數不能定義為純虛函數,因為純虛函數就是沒有實現,在鏈接期會報錯(但是不是像普通函數一樣報抽象類不能實例化對象)。
二、Demo
1.抽象類界面例子
/*main.cpp*/ #include "libhuman.h" int main() { Human *pe = new_english_man(); pe->eating(); pe->wearing(); delete_english_man(pe); return 0; }
/* libhuman.h */ #ifndef _LIBHUMAN_H__ #define _LIBHUMAN_H__ #include <iostream> using namespace std; class Human { int a; public: int b; virtual void eating() = 0; virtual void wearing() = 0; virtual ~Human() { //shouldn't be pure virtual function cout << "~Human()" << endl; } }; Human * new_english_man(); void delete_english_man(Human * ph); #endif
/* English.h */ #ifndef _ENGLISH_H__ #define _ENGLISH_H__ #include <iostream> #include "libhuman.h" using namespace std; class English : public Human { int a[10]; //new add to test public: void eating(); void wearing(); ~English(); }; #endif
/* English.cpp */ #include "English.h" void English::eating() { cout << "English::eating" << endl; } void English::wearing() { cout << "English::wearing" << endl; } English::~English() { cout << "English::~English" << endl; } Human * new_english_man() { return new English(); } void delete_english_man(Human * ph) { delete static_cast<English*>(ph); }
/* Makefile */ main : libHuman.so main.cpp g++ $^ -o $@ -L ./ -lHuman libHuman.so : English.cpp g++ -shared -fPIC -o $@ English.cpp clean: rm -rf libHuman.so *.o main # export LD_LIBRARY_PATH=./ ./main
