自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

EasyC++,繼承和動(dòng)態(tài)內(nèi)存分配

開發(fā) 后端
當(dāng)我們的基類使用動(dòng)態(tài)內(nèi)存分配,并且重新定義賦值和復(fù)制構(gòu)造函數(shù),這會(huì)對(duì)派生類的實(shí)現(xiàn)有什么影響呢?

繼承和動(dòng)態(tài)內(nèi)存分配

今天這篇文章來聊聊繼承與動(dòng)態(tài)內(nèi)存分配。

這里面有一個(gè)問題,當(dāng)我們的基類使用動(dòng)態(tài)內(nèi)存分配,并且重新定義賦值和復(fù)制構(gòu)造函數(shù),這會(huì)對(duì)派生類的實(shí)現(xiàn)有什么影響呢?

我們來看兩種情況。

派生類不用new

假設(shè)基類中使用了動(dòng)態(tài)內(nèi)存分配:

  1. class baseDMA { 
  2.  private: 
  3.      char *label; 
  4.      int rating; 
  5.     public
  6.      baseDMA(const char* l="null"int r=0); 
  7.      baseDMA(const baseDMA& rs); 
  8.      virtual ~baseDMA(); 
  9.      baseDMA &operator=(const baseDMA& rs); 
  10. }; 

在這個(gè)聲明里包含了構(gòu)造函數(shù)、析構(gòu)函數(shù)、復(fù)制構(gòu)造函數(shù)和重載賦值運(yùn)算符。

現(xiàn)在假設(shè)我們從baseDMA派生出了類lackDMA,但是后者不使用new:

  1. class lackDMA: public baseMDA { 
  2.    private: 
  3.      char color[40]; 
  4.     public
  5.      ... 
  6. }; 

問題來了,我們要不要給lackDMA這個(gè)類定義析構(gòu)函數(shù)、復(fù)制構(gòu)造函數(shù)和賦值運(yùn)算符呢?

答案是不需要。

首先是析構(gòu)函數(shù),這個(gè)很好想明白,如果我們沒有定義析構(gòu)函數(shù),那么編譯器會(huì)自動(dòng)定義一個(gè)不執(zhí)行任何操作的默認(rèn)析構(gòu)函數(shù)。實(shí)際上派生類的析構(gòu)函數(shù)往往會(huì)在執(zhí)行一些邏輯之后調(diào)用基類的構(gòu)造函數(shù),因?yàn)閘ackDMA類中的成員不是通過new創(chuàng)建的,因此不需要額外的操作,所以默認(rèn)析構(gòu)函數(shù)是合適的。

同樣的默認(rèn)復(fù)制構(gòu)造函數(shù)也會(huì)執(zhí)行非new創(chuàng)建成員的復(fù)制,所以對(duì)于color變量來說是沒問題的。并且在派生類當(dāng)中,默認(rèn)復(fù)制構(gòu)造函數(shù)除了會(huì)復(fù)制非new創(chuàng)建的成員之外,還會(huì)調(diào)用基類的復(fù)制構(gòu)造函數(shù)來復(fù)制父類成員的部分。所以,對(duì)于派生類lackDMA來說,我們使用默認(rèn)的復(fù)制構(gòu)造函數(shù)一樣沒有問題。

賦值也是一樣的,默認(rèn)的賦值運(yùn)算符也會(huì)自動(dòng)使用基類的賦值運(yùn)算符來對(duì)基類的成員進(jìn)行賦值。

派生類使用new

我們?cè)賮砜纯磁缮惍?dāng)中使用了new的情況。

  1. class hasDMA: public baseMDA { 
  2.    private: 
  3.      char *style; 
  4.     public
  5.      ... 
  6. }; 

在hasDMA這個(gè)類當(dāng)中,我們添加了一個(gè)需要使用new創(chuàng)建的char*成員。在這種情況下,我們就沒辦法使用默認(rèn)的函數(shù)了,就必須定義顯式析構(gòu)函數(shù)、復(fù)制構(gòu)造函數(shù)和賦值運(yùn)算符了,我們一個(gè)一個(gè)來看。

首先是析構(gòu)函數(shù),派生類的析構(gòu)函數(shù)會(huì)自動(dòng)調(diào)用基類的析構(gòu)函數(shù),所以我們只需要在析構(gòu)函數(shù)當(dāng)中釋放派生類中獨(dú)有的成員變量即可。

  1. hasDMA::~hasDMA() { 
  2.     delete []style; 

然后我們?cè)賮砜纯纯截悩?gòu)造函數(shù),由于派生類不能訪問基類private成員,所以我們需要調(diào)用基類的拷貝構(gòu)造函數(shù)。

  1. hasDMA::hasDMA(const hasDMA& hs): baseDMA(hs) { 
  2.     style = new char[std::strlen(hs.style) + 1]; 
  3.     std::strcpy(style, hs.style); 

最后是賦值運(yùn)算符,同樣,由于派生類不能訪問基類中私有成員,我們也需要借助基類的賦值運(yùn)算符:

  1. hasDMA &hasDMA::operator(const hasDMA& hs) { 
  2.     if (this == &hs) return *this; 
  3.     baseDMA::operator=(hs); 
  4.     delete []style; 
  5.     style = new char[std::strlen(hs.style) + 1]; 
  6.     std::strcpy(style, hs.style); 
  7.     return *this; 

這當(dāng)中有一個(gè)語句看起來有些奇怪:

  1. baseDMA::operator=(hs); 

這是我們手動(dòng)顯式調(diào)用了基類的賦值運(yùn)算符,我們直接用等于號(hào)賦值也有同樣的效果:

  1. *this = hs; 

為什么不這么干呢?這是因?yàn)榫幾g器在執(zhí)行的時(shí)候會(huì)默認(rèn)調(diào)用子類的賦值運(yùn)算符hasDMA::operator=,從而導(dǎo)致一直遞歸導(dǎo)致死循環(huán)。

 

所以我們需要手動(dòng)寫明作用域解析符,表明這是調(diào)用的父類賦值運(yùn)算符,而非派生類的運(yùn)算符,這一點(diǎn)比較隱晦,要千萬注意。

 

責(zé)任編輯:武曉燕 來源: Coder梁
相關(guān)推薦

2021-12-01 10:50:31

C++存儲(chǔ)動(dòng)態(tài)

2021-12-30 14:58:58

C++函數(shù)動(dòng)態(tài)

2021-11-09 10:38:16

C++Const指針

2022-01-13 10:30:21

C語言內(nèi)存動(dòng)態(tài)

2021-12-12 18:13:54

C++This指針

2021-12-29 20:31:40

C++多態(tài)指針

2021-12-09 10:56:50

函數(shù)C++原型

2021-11-26 00:03:20

C++編譯常量

2021-11-30 11:04:36

C++函數(shù)語言

2021-10-26 00:19:51

C++結(jié)構(gòu)體存儲(chǔ)

2021-12-08 10:43:09

C++實(shí)現(xiàn)

2021-12-10 10:45:36

C++函數(shù)Stock

2021-11-27 11:50:09

C++靜態(tài)持續(xù)

2021-12-11 19:02:03

函數(shù)C++對(duì)象

2021-12-03 10:48:18

Using編譯指令

2021-11-10 10:48:36

C++函數(shù)指針

2021-12-15 10:25:57

C++運(yùn)算符重載

2021-12-05 18:20:42

C++空間特性

2022-01-04 16:35:42

C++Protected關(guān)鍵字

2021-10-27 16:27:20

C++指針操控
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)