繼承共分為三種 :
public 公有繼承
protected 保護繼承
private 私有繼承
於此同時,每個類中的成員也具有public,protected,private這三種特性,每種特性下的成員在每種繼承方式下都有不同的結果,總結如下:
繼承方式
本來的屬性
轉換後的屬性
public
public
public
public
protected
protected
public
private
無法訪問
使用兩個類來表示,person和worker
worker公有繼承person類,那麼person類中的public 中的成員函式與變數,在worker中都可以直接使用,而person中的protected中的成員函式與變數,則相當於轉移到了worker中的protected中,此時,protected中的成員函式和成員變數,只能由類中的成員函式來呼叫。而private中的,則直接被隱藏了起來,繼承後的worker無法呼叫其中的變數和函式。
繼承方式
本來的屬性
轉換後的屬性
protected
public
protected
protected
protected
protected
protected
private
無法訪問
保護繼承,則是在公有繼承上更進一步,將public和protected全部轉移到派生類中的protected中去,此時,也只有成員函式可以呼叫他們,而private依然不能使用。
私有繼承:
繼承方式
本來的屬性
轉換後的屬性
private
public
private
private
protected
private
private
private
無法訪問
私有繼承,則是和protected類似,將變數全部轉移到派生類中的private中,而本身為private的則無法呼叫。
當你定義了乙個類a,類中包含乙個成員函式void abc();然後類a被類b繼承,但恰巧類b中也有乙個自己獨有的成員函式void abc();這樣就有可能引起不必要的麻煩,於是需要隱藏的這個功能,名字為隱藏,但是**並沒有被隱藏,這兩個abc()函式都存在,只是在呼叫時需要注意一些語句的使用,下面用**來實現:
結果如下:繼承方式 :class
worker
:public person
m_strname 是 person類中的protected變數
//person::play()
void person::
play()
void worker::
play()
此時兩個play()函式都是沒有變數的,如果修改worker 的play()函式,將其修改為void worker::play(int x),那麼此時兩個play()函式就不同了,還會隱藏嗎?
我們將worker的play()修改後,取消person::語句,如下:
計算機會報錯worker workerman;
workerman.
play(7
);workerman.
play()
;
第二行不接受0個引數,說明此時計算機依然會呼叫worker中的play()函式,所以無論引數是否相同,都需要在被隱藏的函式前加上類名::,才可以呼叫。派生類只能呼叫自己的同名成員函式play(),不能呼叫繼承來的同名函式play().也就是說,他們之間無法形成過載,只能形成隱藏。
變數也同理,當派生類中和基類中都有相同的型別,相同名稱的變數時,在子類中直接呼叫只會修改子類中的該變數,而想修改父類中的該變數,依然要在賦值語句中加上類名::變數名,並且此時父類中的該變數也確實被改變,下次直接在父類中呼叫時,也是更改過的值。
所以,is-a體現在派生類可以給基類用來初始化,基類的指標也可以指向派生類的首位址。但反之則會語法錯誤。int
main
(void
)
使用過程
兩者之間的儲存結構也存在以下知識點:void
fun1
(person *p)
void
fun2
(person &p)
intmain()
當用子類賦值給父類時,父類物件只可以呼叫他原本有的變數,而子類特有的成員變數使用父類呼叫則會丟失,使用父類指標指向子類也是,只能指向其本身所擁有的變數。
我們使用基類的指標去指向乙個派生類的物件時,記過一系列操作後,需要delete釋放指標指向的空間,但我們知道is-a關係下,基類指標是無法訪問到某些派生類的變數的,這就會導致不呼叫派生類的析構函式,只呼叫基類的,就有可能造成記憶體洩漏。
解決方法便是使用virtual關鍵字,加在基類析構函式前,如之前的person類和soldier類,virtual ~person,virtual會自動繼承給soldier類,即此時的soldier的析構函式也是virtual ~soldier,這樣就會呼叫兩者的析構函式,所以,使用基類指標去new乙個派生類物件,需要釋放記憶體時,就需要用到virtual關鍵字,這就是虛析構函式。
多繼承:
注意,多繼承時如果不寫繼承模式,則預設為private。class
worker
;class
farmer
;class
migrantworker
:public worker,
public farmer
;
多重繼承:
要牢記之前繼承時的三種繼承模式 public,protected,privateclass
person
;class
soldier
:public person
;class
infantryman
:public solider
;
關鍵字 virtual
用到虛繼承就得了解一下菱形繼承(** 慕課網c++遠征之繼承篇)
可以看到 a->b->d,a->c->d,是兩個多重繼承,而b,c同時繼承給d又是多繼承,這就是菱形繼承,存在的問題是,a中將含有兩個完全一樣的資料,這對於記憶體來說是一種冗餘,所以要消除這種冗餘,就需要使用虛繼承來實現了,而實現的關鍵字就是virtual
使用巨集定義來避免重定義的方法
#ifndef (if not defined) 檔名要大寫 如person.h 要寫成person_h
#define 上面沒定義的
。。。#endif
物件導向特性之 繼承
目錄 六 繼承重用父類方法得兩種方式 繼承 封裝 多型 繼承是一種建立新類的方式,新建的類可以繼承乙個或多個父類 python支援多繼承 父類又可稱為基類或超類,新建的類稱為派生類或子類。父類的屬性和方法,子類中也有。格式就是子類名加括號,括號內是父類名 class a pass class b a...
物件導向特性 繼承
1 子類繼承父類的方法和字段 class computer 子類,膝上型電腦類 class notecomputer extends computer 2 不需要父類的字段和方法,那麼可以採用重寫的方法覆蓋掉父類的方法。class computer 子類,膝上型電腦類 class notecompu...
Python 物件導向的特性2 繼承
物件導向的三大特性 1 封裝 根據職責將屬性和方法封裝到乙個抽象的類中,然後類建立乙個實實在在的物件,有了物件以後,就可以訪問到物件內部的屬性,或者讓物件來呼叫乙個已經封裝好的方法。2 繼承 實現 的重用,相同的 不需要重寫。3 多型 不同的子類物件呼叫相同的父類方法,產生不同的執行結果。以繼承和重...