c 物件導向特性之繼承(2)

2021-09-28 19:13:43 字數 3728 閱讀 9333

繼承共分為三種 :

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().也就是說,他們之間無法形成過載,只能形成隱藏。

變數也同理,當派生類中和基類中都有相同的型別,相同名稱的變數時,在子類中直接呼叫只會修改子類中的該變數,而想修改父類中的該變數,依然要在賦值語句中加上類名::變數名,並且此時父類中的該變數也確實被改變,下次直接在父類中呼叫時,也是更改過的值。

int

main

(void

)

所以,is-a體現在派生類可以給基類用來初始化,基類的指標也可以指向派生類的首位址。但反之則會語法錯誤。

使用過程

void

fun1

(person *p)

void

fun2

(person &p)

intmain()

兩者之間的儲存結構也存在以下知識點:

當用子類賦值給父類時,父類物件只可以呼叫他原本有的變數,而子類特有的成員變數使用父類呼叫則會丟失,使用父類指標指向子類也是,只能指向其本身所擁有的變數。

我們使用基類的指標去指向乙個派生類的物件時,記過一系列操作後,需要delete釋放指標指向的空間,但我們知道is-a關係下,基類指標是無法訪問到某些派生類的變數的,這就會導致不呼叫派生類的析構函式,只呼叫基類的,就有可能造成記憶體洩漏。

解決方法便是使用virtual關鍵字,加在基類析構函式前,如之前的person類和soldier類,virtual ~person,virtual會自動繼承給soldier類,即此時的soldier的析構函式也是virtual ~soldier,這樣就會呼叫兩者的析構函式,所以,使用基類指標去new乙個派生類物件,需要釋放記憶體時,就需要用到virtual關鍵字,這就是虛析構函式。

多繼承:

class

worker

;class

farmer

;class

migrantworker

:public worker,

public farmer

;

注意,多繼承時如果不寫繼承模式,則預設為private。

多重繼承:

class

person

;class

soldier

:public person

;class

infantryman

:public solider

;

要牢記之前繼承時的三種繼承模式 public,protected,private

關鍵字 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 多型 不同的子類物件呼叫相同的父類方法,產生不同的執行結果。以繼承和重...