日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > c/c++ >内容正文

c/c++

C++ primer 第15章 面向对象程序设计

發(fā)布時(shí)間:2023/12/13 c/c++ 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++ primer 第15章 面向对象程序设计 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

  • 前言
  • OOP:概述
    • 繼承
    • 動(dòng)態(tài)綁定
  • 定義基類和派生類
    • 定義基類
      • 成員函數(shù)與繼承
      • 訪問(wèn)控制與繼承
    • 定義派生類
      • 派生類中的虛函數(shù)
      • 派生類對(duì)象及派生類向基類的類型轉(zhuǎn)換
      • 派生類構(gòu)造函數(shù)
      • 派生類使用基類的成員
      • 繼承與靜態(tài)成員
      • 派生類的聲明
      • 被用作基類的類
      • 防止繼承的發(fā)生
    • 類型轉(zhuǎn)換與繼承
      • 靜態(tài)類型與動(dòng)態(tài)類型
      • 在對(duì)象之間不存在類型轉(zhuǎn)換
  • 虛函數(shù)
    • 對(duì)虛函數(shù)的調(diào)用可能在運(yùn)行時(shí)才被解析
    • c++的多態(tài)性
    • 派生類中的虛函數(shù)
    • final和override說(shuō)明符
    • 回避虛函數(shù)的機(jī)制
  • 抽象基類
    • 純虛函數(shù)
    • 含有純虛函數(shù)的類是抽象基類
    • 派生類構(gòu)造函數(shù)只初始化它的直接基類
    • 重構(gòu)
  • 訪問(wèn)控制與繼承
    • 受保護(hù)的成員 protected
    • 公有、私有和受保護(hù)繼承
    • 派生類向基類轉(zhuǎn)換的可訪問(wèn)性
    • 友元與繼承
    • 改變各個(gè)成員的可訪問(wèn)性
    • 默認(rèn)的繼承保護(hù)級(jí)別
  • 繼承中的類作用域
    • 在編譯時(shí)進(jìn)行名字查找
    • 名字沖突與繼承
    • 名字查找先于類型檢查
    • 虛函數(shù)與作用域,通過(guò)基類調(diào)用隱藏的虛函數(shù)
  • 構(gòu)造函數(shù)與拷貝控制
    • 虛析構(gòu)函數(shù)
      • 虛析構(gòu)函數(shù)將阻止合成移動(dòng)操作
    • 合成拷貝控制與繼承
      • 派生類中刪除的拷貝控制與基類的關(guān)系型
    • 派生類的拷貝控制成員
      • 定義派生類的拷貝或移動(dòng)構(gòu)造函數(shù)
      • 派生類賦值運(yùn)算符
      • 派生類析構(gòu)函數(shù)
      • 在構(gòu)造函數(shù)和析構(gòu)函數(shù)中調(diào)用虛函數(shù)
    • 繼承的構(gòu)造函數(shù)
      • 繼承的構(gòu)造函數(shù)的特點(diǎn)
  • 容器與繼承
    • 在容器中放置(智能)指針而非對(duì)象
    • 編寫(xiě)B(tài)asket類
      • decltype的意義
      • [upper_bound可參考chapter 11](https://blog.csdn.net/weixin_43116900/article/details/105916425)
      • 模擬虛拷貝

前言

面向?qū)ο蟪绦蛟O(shè)計(jì)基于三個(gè)基本概念:數(shù)據(jù)抽象、繼承和動(dòng)態(tài)綁定。

繼承和動(dòng)態(tài)綁定對(duì)程序的編寫(xiě)有兩方面的影響:一是我們可以更容易地定義與其他類相似但不完全相同的新類:二是在使用這些彼此相似的類編寫(xiě)程序時(shí), 我們可以在一定程度上忽略掉它們的區(qū)別。

OOP:概述

面向?qū)ο蟪绦蛟O(shè)計(jì)的核心思想是數(shù)據(jù)抽象、繼承和動(dòng)態(tài)綁定。通過(guò)使用數(shù)據(jù)抽象,我們可以將類的接口與實(shí)現(xiàn)分離;使用繼承,可以定義相似的類型并對(duì)其相似關(guān)系建模;使用動(dòng)態(tài)綁定,可以在一定程度上忽略相似類型的區(qū)別,而以統(tǒng)一的方式使用它們的對(duì)象。

繼承

基類負(fù)責(zé)定義在層次關(guān)系中所有類共同擁有的成員,而每個(gè)派生類定義各自特有的成員。

在c++語(yǔ)言中,基類將類型相關(guān)的函數(shù)與派生類不做改變直接繼承的函數(shù)區(qū)分對(duì)待。對(duì)于某些函數(shù),基類希望它的派生類各自定義適合自身的版本,此時(shí)基類就將這些函數(shù)聲明成虛函數(shù)

基類:

class Quote{ public:string isbn() const;virtual double net_price(size_t n) const; };

派生類:

class Bulk_quote : public Quote{ public:double net_price(size_t n) const override; };

因?yàn)锽ulk_quote在它的派生列表中使用了public關(guān)鍵字,因此我們完全可以把Bulk_quote的對(duì)象當(dāng)成Quote的對(duì)象來(lái)使用。

派生類必須在其內(nèi)部對(duì)所有重新定義的虛函數(shù)進(jìn)行聲明。派生類可以在這樣的函數(shù)之前加上virtual關(guān)鍵字, 但是并不是非得這么做。C++11新標(biāo)準(zhǔn)允許派生類顯式地注明它將使用哪個(gè)成員函數(shù)改寫(xiě)基類的虛函數(shù), 具體措施是在該函數(shù)的形參列表之后增加一個(gè)override關(guān)鍵字

動(dòng)態(tài)綁定

通過(guò)使用動(dòng)態(tài)綁定,我們能用同一段代碼分別處理Quote和Bulk_quote的對(duì)象。

double print_total(ostream &os,const Quote &item,size_t n){//根據(jù)item的形參對(duì)象類型調(diào)用Quote::net_price或者Bulk_quote::net_pricedouble ret = item.net_price(n);os<<"ISBN: "<<item.isbn()<<"# sold: "<<n<<"total due: "<<ret<<endl;return ret; }

因?yàn)楹瘮?shù)print_total的item形參是基類Quote的一個(gè)引用,所以,我們既能使用基類Quote的對(duì)象調(diào)用該函數(shù),也能使用派生類Bulk_quote的對(duì)象調(diào)用它。又因?yàn)閜rint_total是使用引用類型調(diào)用net_price函數(shù)的,所以實(shí)際傳入print_total的對(duì)象類型將決定到底執(zhí)行net_price的哪個(gè)版本。

在c++語(yǔ)言中,當(dāng)我們使用基類的引用(或指針)調(diào)用一個(gè)虛函數(shù)時(shí)將發(fā)生動(dòng)態(tài)綁定。

定義基類和派生類

定義基類

基類通常都應(yīng)該定義一個(gè)虛析構(gòu)函數(shù),即使該函數(shù)不執(zhí)行任何實(shí)際操作也是如此。

成員函數(shù)與繼承

在c++語(yǔ)言中,基類必須將它的兩種成員函數(shù)區(qū)分開(kāi)來(lái):一種是基類希望其派生類進(jìn)行覆蓋的函數(shù);另一種是基類希望派生類直接繼承而不要改變的函數(shù)。對(duì)于前者,基類通常將其定義為虛函數(shù),當(dāng)我們使用指針或引用來(lái)調(diào)用虛函數(shù)時(shí),該調(diào)用將被動(dòng)態(tài)綁定。根據(jù)引用或指針?biāo)壎ǖ膶?duì)象類型不同,該調(diào)用可能執(zhí)行基類的版本,也可能執(zhí)行某個(gè)派生類的版本。

基類通過(guò)在其成員函數(shù)的聲明語(yǔ)句之前加上關(guān)鍵字virtual使得該函數(shù)執(zhí)行動(dòng)態(tài)綁定。任何構(gòu)造函數(shù)之外的非靜態(tài)函數(shù)都可以是虛函數(shù)。關(guān)鍵字 virtual只能出現(xiàn)在類內(nèi)部的聲明語(yǔ)句之前而不能用于類外部的函數(shù)定義。如果基類把一個(gè)函數(shù)聲明成虛函數(shù),則該函數(shù)在派生類中隱式地也是虛函數(shù)

成員函數(shù)如果沒(méi)被聲明為虛函數(shù),則其解析過(guò)程發(fā)生在編譯時(shí)而非運(yùn)行時(shí)。isbn函數(shù)的執(zhí)行與派生類的細(xì)節(jié)無(wú)關(guān),無(wú)論是Quote對(duì)象還是Bulk_quote對(duì)象,isbn函數(shù)的行為都一樣。

訪問(wèn)控制與繼承

派生類可以繼承定義在基類中的成員,但是派生類的成員函數(shù)不一定有權(quán)訪問(wèn)從基類繼承而來(lái)的成員。和其他使用基類的代碼一樣,派生類能訪問(wèn)公有成員,而不能訪問(wèn)私有成員。不過(guò)在某些時(shí)候基類中還有這樣一種成員,基類希望它的派生類有權(quán)訪問(wèn)該成員同時(shí)禁止其他用戶訪問(wèn)。我們用受保護(hù)的(protected)訪問(wèn)運(yùn)算符說(shuō)明這樣的成員。

我們的Quote類希望它的派生類定義各自的net_price函數(shù),因此派生類需要訪問(wèn)Quote的price成員。此時(shí)我們將price定義成受保護(hù)的。與之相反,派生類訪問(wèn)bookNo成員的方式與其他用戶是樣的,都是通過(guò)調(diào)用isbn函數(shù),因此bookNo被定義成私有的,即使是Quote派生出來(lái)的類也不能直接訪問(wèn)它。

定義派生類

派生類必須通過(guò)使用類派生列表明確指出它是從哪個(gè)(哪些)基類繼承而來(lái)的。類派生列表的形式是:首先是一個(gè)冒號(hào),后面緊跟以逗號(hào)分隔的基類列表,其中每個(gè)基類前面可以有以下三種訪問(wèn)說(shuō)明符中的一個(gè):public、protected或者private。

訪問(wèn)說(shuō)明符的作用是控制派生類從基類繼承而來(lái)的成員是否對(duì)派生類的用戶可見(jiàn)。

如果一個(gè)派生類是公有的,則基類的公有成員也是派生類接口的組成部分。此外,我們能將公有派生類型的對(duì)象綁定到基類的引用或指針上。因?yàn)槲覀冊(cè)谂缮斜碇惺褂昧藀ublic,所以Bulk_quote的接口隱式地包含isbn函數(shù),同時(shí)在任何需要Quote的引用或指針的地方我們都能使用Bulk_quote的對(duì)象。

派生類中的虛函數(shù)

派生類經(jīng)常(但不總是)覆蓋它繼承的虛函數(shù)。如果派生類沒(méi)有覆蓋其基類中的某個(gè)虛函數(shù),則該虛函數(shù)的行為類似于其他的普通成員,派生類會(huì)直接繼承其在基類中的版本。

派生類對(duì)象及派生類向基類的類型轉(zhuǎn)換

一個(gè)派生類對(duì)象包含多個(gè)組成部分:一個(gè)含有派生類自己定義的(非靜態(tài))成員的子對(duì)象,以及一個(gè)與該派生類繼承的基類對(duì)應(yīng)的子對(duì)象,如果有多個(gè)基類,那么這樣的子對(duì)象也有多個(gè)。

因?yàn)樵谂缮悓?duì)象中含有與其基類對(duì)應(yīng)的組成部分,所以我們能把派生類的對(duì)象當(dāng)成基類對(duì)象來(lái)使用,而且我們也能將基類的指針或引用綁定到派生類對(duì)象中的基類部分。

Quote item; //基類對(duì)象 Bulk_quote bulk; //派生類對(duì)象 Quote *p = &item; //p指向Quote對(duì)象 p = &bulk; //p指向bulk的Quote部分 Quote &r = bulk; //r綁定到bulk的Quote部分

這種轉(zhuǎn)換通常稱為派生類到基類的類型轉(zhuǎn)換。和其他類型一樣,編譯器會(huì)隱式地執(zhí)行派生類到基類的轉(zhuǎn)換。我們可以把派生類對(duì)象或者派生類對(duì)象的引用用在需要基類引用的地方;同樣的,我們也可以把派生類對(duì)象的指針用在需要基類指針的地方。

派生類構(gòu)造函數(shù)

盡管在派生類對(duì)象中含有從基類繼承而來(lái)的成員,但是派生類并不能直接初始化這些成員。派生類必須使用基類的構(gòu)造函數(shù)來(lái)初始化它的基類部分。

派生類構(gòu)造函數(shù)同樣是通過(guò)構(gòu)造函數(shù)初始化列表來(lái)將實(shí)參傳遞給基類構(gòu)造函數(shù)的。例如:

Bulk_quote::Bulk_quote(const string& book, double p, size_t qty, double disc):Quote(book,p),min_qty(qty),discount(disc){}

除非我們特別指出,否則派生類對(duì)象的基類部分會(huì)像數(shù)據(jù)成員一樣執(zhí)行默認(rèn)初始化。如果想使用其他的基類構(gòu)造函數(shù),我們需要以類名加圓括號(hào)內(nèi)的實(shí)參列表的形式為構(gòu)造函數(shù)提供初始值。

首先初始化基類的部分,然后按照聲明的順序依次初始化派生類的成員。

派生類使用基類的成員

派生類可以訪問(wèn)基類的公有成員和受保護(hù)成員。

繼承與靜態(tài)成員

**如果基類定義了一個(gè)靜態(tài)成員,則在整個(gè)繼承體系中只存在該成員的唯一定義。**不論從基類中派生出來(lái)多少個(gè)派生類,對(duì)于每個(gè)靜態(tài)成員來(lái)說(shuō)都只存在唯一的實(shí)例。

靜態(tài)成員遵循通用的訪問(wèn)控制規(guī)則,如果基類中的成員是private的,則派生類無(wú)權(quán)訪問(wèn)它。假設(shè)某靜態(tài)成員是可訪問(wèn)的,則我們既能通過(guò)基類使用它也能通過(guò)派生類使用它。

class Base { public:static void statmem() {cout << "這是Base的靜態(tài)函數(shù)statmem()"<< endl;}}; class Derived:public Base { public:void f(const Derived& obj) {Base::statmem();Derived::statmem();obj.statmem(); //通過(guò)Derived對(duì)象訪問(wèn)statmem(); //通過(guò)this對(duì)象訪問(wèn)} };

輸出結(jié)果:

這是Base的靜態(tài)函數(shù)statmem() 這是Base的靜態(tài)函數(shù)statmem() 這是Base的靜態(tài)函數(shù)statmem() 這是Base的靜態(tài)函數(shù)statmem()

派生類的聲明

派生類的聲明與其他類差別不大,聲明中包含類名但是不包含它的派生列表:

class Bulk_quote : public Quote; 錯(cuò)誤,聲明不包含派生列表 class Bulk_quote; 正確

被用作基類的類

如果我們想將某個(gè)類用作基類,則該類必須已經(jīng)定義而非僅僅聲明。所以,一個(gè)類不能派生它本身

每個(gè)類都會(huì)繼承直接基類的所有成員。對(duì)于一個(gè)最終類來(lái)說(shuō),它會(huì)繼承其直接基類的成員,該直接基類的成員又含有其基類的成員,以此類推,最終的派生類將包含它的直接基類的子對(duì)象以及每個(gè)間接基類的子對(duì)象。

防止繼承的發(fā)生

防止繼承發(fā)生的方法,即在類名后跟一個(gè)關(guān)鍵字final:

class NoDerived final{}; NoDerived不能作為基類 class Last final:public Base{}; Last不能作為基類

類型轉(zhuǎn)換與繼承

通常情況下,如果我們想把引用或指針綁定到一個(gè)對(duì)象上,則引用或指針的類型應(yīng)與對(duì)象的類型一致,或者對(duì)象的類型含有一個(gè)可接受的const類型轉(zhuǎn)換規(guī)則。存在繼承關(guān)系的類是一個(gè)重要的例外:我們可以將基類的指針或引用綁定到派生類對(duì)象上。

我們可以將基類的指針或引用綁定到派生類對(duì)象上,這意味著,當(dāng)使用基類的引用(或指針)時(shí),實(shí)際上我們并不清楚該引用(或指針)所綁定對(duì)象的真實(shí)類型。該對(duì)象可能是基類的對(duì)象,也可能是派生類的對(duì)象。

和內(nèi)置指針一樣,智能指針類也支持派生類向基類的類型轉(zhuǎn)換,這意味著我們可以將一個(gè)派生類對(duì)象的指針存儲(chǔ)在一個(gè)基類的智能指針類。

靜態(tài)類型與動(dòng)態(tài)類型

當(dāng)我們使用存在繼承關(guān)系的類型時(shí),必須將一個(gè)變量或其他表達(dá)式的靜態(tài)類型與該表達(dá)式表示對(duì)象的動(dòng)態(tài)類型區(qū)分開(kāi)來(lái)。表達(dá)式的靜態(tài)類型在編譯時(shí)總是已知的,它的變量聲明時(shí)的類型或表達(dá)式生成的類型,動(dòng)態(tài)類型則是變量或表達(dá)式表示的內(nèi)存中的對(duì)象的類型。動(dòng)態(tài)類型直到運(yùn)行時(shí)才可知。

如果一個(gè)變量非指針也非引用,則它的靜態(tài)類型和動(dòng)態(tài)類型永遠(yuǎn)一致。但基類的指針或引用的動(dòng)態(tài)類型可能與其動(dòng)態(tài)類型不一致。

不存在從基類向派生類的隱式類型轉(zhuǎn)換。

在對(duì)象之間不存在類型轉(zhuǎn)換

派生類向基類的自動(dòng)類型轉(zhuǎn)換只對(duì)指針或引用類型有效,在派生類類型和基類類型之間不存在這樣的轉(zhuǎn)換。

當(dāng)我們用一個(gè)派生類對(duì)象為一個(gè)基類對(duì)象初始化或賦值時(shí),只有該派生類對(duì)象中的基類部分會(huì)被拷貝、移動(dòng)或賦值,它的派生類部分將被忽略掉。

虛函數(shù)

當(dāng)我們使用基類的引用或指針調(diào)用一個(gè)虛成員函數(shù)時(shí)會(huì)執(zhí)行動(dòng)態(tài)綁定。

我們必須為每一個(gè)虛函數(shù)都提供定義,而不管它是否被用到了。

對(duì)虛函數(shù)的調(diào)用可能在運(yùn)行時(shí)才被解析

當(dāng)某個(gè)虛函數(shù)通過(guò)指針或引用調(diào)用時(shí),編譯器產(chǎn)生的代碼直到運(yùn)行時(shí)才能確定應(yīng)該調(diào)用哪個(gè)版本的函數(shù)。被調(diào)用的函數(shù)是與綁定到指針或引用上的對(duì)象的動(dòng)態(tài)類型相匹配的那一個(gè)。

當(dāng)我們通過(guò)一個(gè)具有普通類型(非引用非指針)的表達(dá)式調(diào)用虛函數(shù)時(shí),在編譯時(shí)就會(huì)將調(diào)用的版本確定下來(lái)。

c++的多態(tài)性

OOP的核心思想是多態(tài)性(polymorphism)。多態(tài)性這個(gè)詞源自希臘語(yǔ),其含義是“多種形式”。我們把具有繼承關(guān)系的多個(gè)類型稱為多態(tài)類型,因?yàn)槲覀兡苁褂眠@些類型的“多種形式”而無(wú)須在意它們的差異。引用或指針的靜態(tài)類型與動(dòng)態(tài)類型不同這一事實(shí)正是C++語(yǔ)言支持多態(tài)性的根本所在

當(dāng)我們使用基類的引用或指針調(diào)用基類中定義的一個(gè)函數(shù)時(shí),我們并不知遞該函數(shù)真正作用的對(duì)象是什么類型,因?yàn)樗赡苁且粋€(gè)基類的對(duì)象也可能是一個(gè)派生類的對(duì) 象。如果該函數(shù)是虛函數(shù),則直到運(yùn)行時(shí)才會(huì)決定到底執(zhí)行哪個(gè)版本,判斷的依據(jù)是引用或指針?biāo)壎ǖ膶?duì)象的真實(shí)類型。

另一方面,對(duì)非虛函數(shù)的調(diào)用在編譯時(shí)進(jìn)行綁定。類似的,通過(guò)對(duì)象進(jìn)行的函數(shù)(虛函數(shù)或非虛函數(shù))調(diào)用也在編譯時(shí)綁定。 對(duì)象的類型是確定不變的,我們無(wú)論如何都不可能令對(duì)象的動(dòng)態(tài)類型與靜態(tài)類型不一致。因此,通過(guò)對(duì)象進(jìn)行的函數(shù)調(diào)用將在編譯時(shí)綁定到該對(duì)象所屬類中的函數(shù)版本上。

當(dāng)且僅當(dāng)對(duì)通過(guò)指針或引用調(diào)用虛函數(shù)時(shí),才會(huì)在運(yùn)行時(shí)解析該調(diào)用,也只有在這種情況下對(duì)象的動(dòng)態(tài)類型才有可能與靜態(tài)類型不同。

派生類中的虛函數(shù)

當(dāng)我們?cè)谂缮愔叙⑸w了某個(gè)虛函數(shù)時(shí),可以再一次使用virtual關(guān)鍵字指出該函數(shù)的性質(zhì)。然而這么做并非必須,因?yàn)橐坏┠硞€(gè)函數(shù)被聲明成虛函數(shù),則在所有派生類中它都是虛函數(shù)。

派生類中虛函數(shù)的返回類型也必須與基類函數(shù)匹配。該規(guī)則存在一個(gè)例外,當(dāng)類的虛函數(shù)返回類型是類本身的指針或引用時(shí),上述規(guī)則無(wú)效。也就是說(shuō),如果D由B派生得到則基類的虛函數(shù)可以返回B*而派生類的對(duì)應(yīng)函數(shù)可以返回D*,只不過(guò)這樣的返回類型要求從D到B的類型轉(zhuǎn)換是可訪問(wèn)的。

基類中的虛函數(shù)在派生類中隱含地也是一個(gè)虛函數(shù)。當(dāng)派生類覆蓋了某個(gè)虛函數(shù)時(shí),該函數(shù)在基類中的形參必須與派生類中的形參嚴(yán)格匹配。

final和override說(shuō)明符

派生類如果定義了一個(gè)函數(shù)與基類中虛函數(shù)的名字相同但是形參列表不同,這仍然是合法的行為,編譯器將認(rèn)為新定義的這個(gè)函數(shù)與基類中原有的函數(shù)是相互獨(dú)立的。

在c++11新標(biāo)準(zhǔn)中,我們可以使用override關(guān)鍵字來(lái)說(shuō)明派生類中的虛函數(shù)。如果我們使用override標(biāo)記了某個(gè)函數(shù),但該函數(shù)并沒(méi)有覆蓋已存在的虛函數(shù),此時(shí)編譯器將會(huì)報(bào)錯(cuò)。

class B { virtual void fl(int) const; virtual void f2(); void f3 (); };class Dl : B { void fl(int) const override; //正確:fl與基類中的fl匹配 void f2(int) override; //錯(cuò)誤:B沒(méi)有形如f2(int)的函數(shù)void f3() override; //錯(cuò)誤:f3不是虛函數(shù) void f4 () override; //錯(cuò)誤:B沒(méi)有名為f4的函數(shù) };

我們還能把某個(gè)函數(shù)指定為final,如果我們已經(jīng)把函數(shù)定義成final了,則之后任何嘗試覆蓋該函數(shù)的操作都將會(huì)引發(fā)錯(cuò)誤。

class D2:B{ //從B繼承f2()和f3(),覆蓋f1(int)void f1(int)const final; // 不允許后續(xù)的其他類覆蓋f1(int) }class D3:D2{void f2(); //正確:覆蓋從間接基類B繼承而來(lái)的f2void f1(int)const; //錯(cuò)誤:D2已經(jīng)將f2聲明成final }

回避虛函數(shù)的機(jī)制

在某些情況下,我們希望對(duì)虛函數(shù)的調(diào)用不要進(jìn)行動(dòng)態(tài)綁定,而是強(qiáng)迫其執(zhí)行虛函數(shù)的某個(gè)特定版本。使用作用域運(yùn)算符可以實(shí)現(xiàn)這一目的。

如果一個(gè)派生類虛函數(shù)需要調(diào)用它的基類版本,但是沒(méi)有使用作用域運(yùn)算符,則在運(yùn)行時(shí)該調(diào)用將被解析為對(duì)派生類版本自身的調(diào)用,從而導(dǎo)致無(wú)限遞歸。

抽象基類

純虛函數(shù)

和普通的虛函數(shù)不一樣,一個(gè)純虛函數(shù)無(wú)須定義。我們通過(guò)在函數(shù)體的位置(即在聲明語(yǔ)句的分號(hào)之前)書(shū)寫(xiě) =0 就可以將一個(gè)虛函數(shù)說(shuō)明為純虛函數(shù)。其中 =0 只能出現(xiàn)在類內(nèi)部的虛函數(shù)聲明語(yǔ)句處。

class Disc_quote : public Quote { public:Disc_quote() = default;Disc_quote(const string& book, double p, size_t qty, double disc):Quote(book, p), min_qty(qty), discount(disc) {}double net_price(size_t n) const = 0; protected:size_t min_qty=0; //折扣適用的購(gòu)買量double discount = 0.0; //表示折扣的小數(shù)值 };

我們也可以為純虛函數(shù)提供定義,不過(guò)函數(shù)體必須定義在類的外部,也就是說(shuō),我們不能在類的內(nèi)部為一個(gè) =0 的函數(shù)提供函數(shù)體。

含有純虛函數(shù)的類是抽象基類

含有(或者未經(jīng)覆蓋直接繼承)純虛函數(shù)的類是抽象基類。抽象基類負(fù)責(zé)定義接口,而后續(xù)其他類可以覆蓋該接口。我們不能(直接)創(chuàng)建一個(gè)抽象基類的對(duì)象。因?yàn)镈isc_quote將net_price定義成了純虛函數(shù),所以我們不能定義Disc_quote的對(duì)象,我們可以定義Disc_quote的派生類的對(duì)象,前提是這些類覆蓋了net_price函數(shù)。

Disc_quote的派生類必須給出自己的net_price定義,否則它們?nèi)詫⑹浅橄蠡悺?/p>

派生類構(gòu)造函數(shù)只初始化它的直接基類

重構(gòu)

在Quote的繼承體系中增加Disc_quote類是重構(gòu)(refactoring)的一個(gè)典型示例。重構(gòu)負(fù)責(zé)重新設(shè)計(jì)類的體系以便將操作和/或數(shù)據(jù)從一個(gè)類移動(dòng)到另一個(gè)類中。對(duì)于面向?qū)ο蟮膽?yīng)用程序來(lái)說(shuō),重構(gòu)是一種很普遍的現(xiàn)象。
值得注意的是,即使我們改變了整個(gè)繼承體系,那些使用了Bulk_quote或Quote 的代碼也無(wú)須進(jìn)行任何改動(dòng)。不過(guò)一旦類被重構(gòu)(或以其他方式被改變),就意味著我們必須重新編譯含有這些類的代碼了。

訪問(wèn)控制與繼承

每個(gè)類分別控制自己的成員初始化過(guò)程,與之類似,每個(gè)類還分別控制著其成員對(duì)于派生類來(lái)說(shuō)是否可訪問(wèn)。

受保護(hù)的成員 protected

  • 和私有成員類似,受保護(hù)的成員對(duì)于類的用戶來(lái)說(shuō)是不可訪問(wèn)的
  • 和公有成員類似,受保護(hù)的成員對(duì)千派生類的成員和友元來(lái)說(shuō)是可訪問(wèn)的。
  • 派生類的成員或友元只能通過(guò)派生類對(duì)象來(lái)訪問(wèn)基類的受保護(hù)成員。派生類對(duì)于一個(gè)基類對(duì)象中的受保護(hù)成員沒(méi)有任何訪問(wèn)特權(quán)。
class Base{ protected:int mem; };class Sneaky : public Base{friend void clobber(Sneaky&); //能訪問(wèn)Sneaky::memfriend void clobber(Base&); //不能訪問(wèn) Base::mem };

公有、私有和受保護(hù)繼承

publicprotectedprivate
公有繼承publicprotected不可見(jiàn)
私有繼承privateprivate不可見(jiàn)
保護(hù)繼承protectedprotected不可見(jiàn)

某個(gè)類對(duì)其繼承而來(lái)的成員的訪問(wèn)權(quán)限受到兩個(gè)因素影響:一是在基類中該成員的訪問(wèn)說(shuō)明符,二是在派生類的派生列表中的訪問(wèn)說(shuō)明符。

派生訪問(wèn)說(shuō)明符對(duì)于派生類的成員(及友元)能否訪問(wèn)其直接基類的成員沒(méi)什么影響。 對(duì)基類成員的訪問(wèn)權(quán)限只與基類中的訪問(wèn)說(shuō)明符有關(guān)。

派生訪問(wèn)說(shuō)明符的目的是控制派生類用戶(包括派生類的派生類在內(nèi))對(duì)于基類成員的訪問(wèn)權(quán)限。

故,示例如下:

繼承代碼:

class Base2 { public:void publicFun() {cout << "Base2的publicFun()" << endl;} private:void privateFun() {cout << "Base2的privateFun()" << endl;} protected:void protectedFun() {cout << "Base2的protectedFun()" << endl;}};class Public_derv : public Base2 { public:void f1() { cout << "Public_derv調(diào)用publicFun() ";publicFun(); }//void f2() { privateFun(); } //派生類不能訪問(wèn)private成員void f3() { cout << "Public_derv調(diào)用protectedFun() ";protectedFun(); } };class Private_derv : private Base2 { public:void f1() { cout << "Private_derv調(diào)用publicFun() ";publicFun(); }//void f2() { privateFun(); } //派生類不能訪問(wèn)private成員void f3() { cout << "Private_derv調(diào)用protectedFun() ";protectedFun(); } };class Protected_derv : protected Base2 { public:void f1() { cout << "Protected_derv調(diào)用publicFun() ";publicFun(); }//void f2() { privateFun(); } //派生類不能訪問(wèn)private成員void f3() { cout << "Protected_derv調(diào)用protectedFun() ";protectedFun(); } };

測(cè)試代碼:

Public_derv public_d;public_d.f1();public_d.f3();public_d.publicFun();Private_derv private_d;private_d.f1();private_d.f3();//private_d.publicFun(); publicFun()在派生類中是private的,不可訪問(wèn)Protected_derv protected_d;protected_d.f1();protected_d.f3();//protected_d.publicFun(); publicFun()在派生類中是protected的,不可訪問(wèn)

輸出結(jié)果:

Public_derv調(diào)用publicFun() Base2的publicFun() Public_derv調(diào)用protectedFun() Base2的protectedFun() Base2的publicFun() Private_derv調(diào)用publicFun() Base2的publicFun() Private_derv調(diào)用protectedFun() Base2的protectedFun() Protected_derv調(diào)用publicFun() Base2的publicFun() Protected_derv調(diào)用protectedFun() Base2的protectedFun()

派生類向基類轉(zhuǎn)換的可訪問(wèn)性

  • 只有當(dāng)D公有的繼承B時(shí),用戶代碼才能使用派生類向基類的轉(zhuǎn)換;如果D繼承B的方式是受保護(hù)的或者私有的,則用戶代碼不能使用該轉(zhuǎn)換
  • 不論D以什么方式繼承B,D的成員函數(shù)和友元都能使用派生類向基類的轉(zhuǎn)換;派生類向其直接基類的類型轉(zhuǎn)換對(duì)于派生類的成員和友元來(lái)說(shuō)永遠(yuǎn)是可訪問(wèn)的。
  • 如果D繼承B的方式是公有的或者受保護(hù)的,則D的派生類的成員和友元可以使用D向B的類型轉(zhuǎn)換,反之,如果D繼承B是私有的,則不能使用。

友元與繼承

就像友元關(guān)系不能傳遞一樣,友元關(guān)系同樣也不能繼承。基類的友元在訪問(wèn)派生類成員時(shí)不具有特殊性,類似的,派生類的友元也不能隨意訪問(wèn)基類的成員。

對(duì)于f2函數(shù),Pal是Base的友元,Pal能夠訪問(wèn)Base對(duì)象的成員,這種可訪問(wèn)性包括了Base對(duì)象內(nèi)嵌在其派生類對(duì)象中的情況。
當(dāng)一個(gè)類將另一個(gè)類聲明為友元時(shí),這種友元關(guān)系只對(duì)做出聲明的類有效。對(duì)于原來(lái)那個(gè)類來(lái)說(shuō),其友元的基類或者派生類不具有特殊的訪問(wèn)能力。

class Base { public:friend class Pal;static void statmem(){} private:void BaseFun() {cout << "這是Base的函數(shù)BaseFun()"<< endl;}};class Sneaky : public Base{ private:void SneakFun(){cout << "這是Sneak的函數(shù)SneakFun()" << endl;} };class Pal { public:void f1(Base b) { b.BaseFun(); }void f2(Sneaky s) { s.BaseFun(); } //void f3(Sneaky s) { s.SneakFun(); } 錯(cuò)誤,Pal不是Sneaky的友元不能訪問(wèn)SneakFun() };class D2 : public Pal{ public://void f(Base b){b.BaseFun(); } 錯(cuò)誤,友元關(guān)系不能繼承 };

改變各個(gè)成員的可訪問(wèn)性

有時(shí)我們需要改變派生類繼承的某個(gè)名字的訪問(wèn)級(jí)別,通過(guò)使用using聲明可以達(dá)到這一目的。

class Base3 { public:size_t size()const { return n; } protected:size_t n; }; class Derived : private Base3 { public:using Base3::size; protected:using Base3::n; };

因?yàn)镈erived是私有繼承,所以繼承而來(lái)的成員size和n是Derived的私有成員,然而我們使用using聲明語(yǔ)句,將size變成了public成員,Derived變成了protected成員,改變了這些成員的可訪問(wèn)性。

默認(rèn)的繼承保護(hù)級(jí)別

class Base{ }; struct D1 : Base{ }; //默認(rèn)public繼承 class D2 : Base{ }; //默認(rèn)private繼承

繼承中的類作用域

每個(gè)類定義自己的作用域,在這個(gè)作用域內(nèi)我們定義類的成員。當(dāng)存在繼承關(guān)系時(shí),派生類的作用域嵌套在其基類的作用域之內(nèi),如果一個(gè)名字在派生類的作用域內(nèi)無(wú)法正確解析,則編譯器將繼續(xù)在外層的基類作用域中尋找該名字的定義。

恰恰因?yàn)轭愖饔糜蛴羞@種繼承嵌套的關(guān)系,所以派生類才能像使用自己的成員一樣使用基類的成員。

在編譯時(shí)進(jìn)行名字查找

一個(gè)對(duì)象、引用或指針的靜態(tài)類型決定了該對(duì)象的哪些成員是可見(jiàn)的。即使靜態(tài)類型與動(dòng)態(tài)類型可能不一致(當(dāng)使用基類的引用或指針時(shí)會(huì)發(fā)生這種情況),但是我們能使用哪些成員仍然是由靜態(tài)類型決定的。

示例:

class D_Quote : public Quote{ public:void fun(){} }D_Quote tmp; D_Quote *dq = &tmp; Quote *q = &tmp;dq->fun(); //正確,dq的類型是D_Quote* q->fun(); //錯(cuò)誤,q的類型是Quote*,沒(méi)有fun()函數(shù)

名字沖突與繼承

和其他作用域一樣,派生類也能重用定義在其直接基類或間接基類中的名字,此時(shí)定義在內(nèi)層作用域(即派生類)的名字將隱藏定義在外層作用域(即基類)的名字。

派生類的成員將隱藏同名的基類成員。

除了覆蓋繼承而來(lái)的虛函數(shù)之外,派生類最好不要重用其他定義在基類中的名字。

名字查找先于類型檢查

如果派生類的成員與基類的某個(gè)成員同名,則派生類將在其作用域內(nèi)隱藏該基類成員。即使派生類成員和基類成員的形參列表不一致,基類成員也仍然會(huì)被隱藏掉。

示例:

class Base{ public:void fun(); };class Derived : public Base{ public:void fun(int); //即使派生類成員和基類成員的形參列表不一致,基類成員fun()也仍然會(huì)被隱藏掉 };Derived d; Base b; d.fun(10); d.fun();//錯(cuò)誤,fun()被隱藏 d.Base::fun(); //正確,調(diào)用Base::fun()

虛函數(shù)與作用域,通過(guò)基類調(diào)用隱藏的虛函數(shù)

class BaseHide { public:virtual void fcn() { cout << "BaseHide virtual fcn()" << endl; }//虛函數(shù) };class DerivedHide1 : public BaseHide { public:void fcn(int) { cout << "DerivedHide1 fcn(int)" << endl; } //隱藏BaseHide的fcn()virtual void f2() { cout << "DerivedHide1 virtual f2( )" << endl; } };class DerivedHide2 : public DerivedHide1 { public:void fcn(int) { cout << "DerivedHide2 fcn(int)" << endl; }void fcn() { cout << "DerivedHide2 fcn()" << endl; }void f2() { cout << "DerivedHide2 f2( )" << endl; } };

測(cè)試代碼:

BaseHide bh;DerivedHide1 dh1;DerivedHide2 dh2;BaseHide *bp1 = &bh, *bp2 = &dh1, *bp3 = &dh2;bp1->fcn(); //虛調(diào)用,BaseHide::fcn()bp2->fcn(); //虛調(diào)用,BaseHide::fcn()bp3->fcn(); //虛調(diào)用,DerivedHide2::fcn()cout << endl;DerivedHide1 *dp1 = &dh1;DerivedHide2 *dp2 = &dh2;//bp2->f2(); 錯(cuò)誤,BaseHide沒(méi)有名為f2的成員dp1->f2(); //虛調(diào)用,DerivedHide1::f2()dp2->f2(); //虛調(diào)用,DerivedHide2::f2()cout << endl;BaseHide *p1= &dh2;DerivedHide1 *p2 = &dh2;DerivedHide2 *p3 = &dh2;//p1->fcn(42); 錯(cuò)誤,BaseHide沒(méi)有fcn(int)p2->fcn(42); //靜態(tài)綁定,DerivedHide1::fcn(int)p3->fcn(42); //靜態(tài)綁定,DerivedHide2::fcn(int)

結(jié)果:

BaseHide virtual fcn() BaseHide virtual fcn() DerivedHide2 virtual fcn()DerivedHide1 virtual f2( ) DerivedHide2 virtual f2( )DerivedHide1 fcn(int) DerivedHide2 fcn(int)

DerivedHide1的fcn函數(shù)并沒(méi)有覆蓋BaseHide的虛函數(shù)fcn,原因是參數(shù)列表不同,將隱藏BaseHide的fcn。
dh1不能調(diào)用fcn(),因?yàn)楸浑[藏了,但bp2指針能調(diào)用fcn(),因?yàn)閒cn是虛函數(shù),bp2實(shí)際綁定的對(duì)象是DerivedHide1類型,而DerivedHide1并沒(méi)有覆蓋不接受實(shí)參的fcn(),所以通過(guò)bp2進(jìn)行的調(diào)用將在運(yùn)行時(shí)解析為BaseHide定義的版本。

bp2指向派生類對(duì)象DerivedHide1,但由于Base類中沒(méi)有f2(),所以bp2不能調(diào)用f2()。

同理,p1不能調(diào)用fcn(int),但p2可以調(diào)用fcn(int),因?yàn)镈erivedHide1中有fcn(int),由于fcn(int)是非虛函數(shù),所以不會(huì)發(fā)生動(dòng)態(tài)綁定,實(shí)際調(diào)用的函數(shù)版本由指針的靜態(tài)類型決定。

構(gòu)造函數(shù)與拷貝控制

和其他類一樣,位于繼承體系中的類也需要控制當(dāng)其對(duì)象執(zhí)行一系列操作時(shí)發(fā)生什么樣的行為,這些操作包括創(chuàng)建、拷貝、移動(dòng)、賦值和銷毀。如果一個(gè)類(基類或派生類)沒(méi)有定義拷貝控制操作,則編譯器將為它合成一個(gè)版本。

虛析構(gòu)函數(shù)

基類通常應(yīng)該定義一個(gè)虛析構(gòu)函數(shù),這樣我們就能動(dòng)態(tài)分配繼承體系中的對(duì)象了。

如果我們delete一個(gè)Base * 類型的指針,則該指針有可能實(shí)際上指向了一個(gè)Derived類型的對(duì)象, 因此編譯器必須清楚它應(yīng)該執(zhí)行的的Derived類型的析構(gòu)函數(shù)。和其他函數(shù)一樣,我們通過(guò)在基類中將析構(gòu)函數(shù)定義成虛函數(shù)以確保執(zhí)行正確的析構(gòu)函數(shù)版本。

如果基類的析構(gòu)函數(shù)不是虛函數(shù),則delete一個(gè)指向派生類對(duì)象的基類指針將產(chǎn)生未定義的行為。

之前我們?cè)榻B過(guò)一條經(jīng)驗(yàn)準(zhǔn)則, 即如果一個(gè)類需要析構(gòu)函數(shù), 那么它也同樣需要 貝和賦值操作。 基類的析構(gòu)函數(shù)并不遵循上述準(zhǔn)則, 它是一個(gè)重要的例外。 一個(gè)基類總是需要析構(gòu)函數(shù), 而且它能將析構(gòu)函數(shù)設(shè)定為虛函數(shù)。 此時(shí),該析構(gòu)函數(shù)為了成為虛函數(shù)而令內(nèi)容為空,我們顯然無(wú)法由此推斷該基類還需要賦值運(yùn)算符或拷貝構(gòu)造函數(shù)。

虛析構(gòu)函數(shù)將阻止合成移動(dòng)操作

基類需要一個(gè)虛析構(gòu)函數(shù)這一事實(shí)還會(huì)對(duì)基類和派生類的定義產(chǎn)生另外一個(gè)間接的影響:如果一個(gè)類定義了析構(gòu)函數(shù),即使它通過(guò) =default 的形式使用了合成的版本,編譯器也不會(huì)為這個(gè)類合成移動(dòng)操作。

合成拷貝控制與繼承

派生類中刪除的拷貝控制與基類的關(guān)系型

  • 如果基類中的默認(rèn)構(gòu)造函數(shù)、拷貝構(gòu)造函數(shù)、拷貝賦值運(yùn)算符或析構(gòu)函數(shù)是被刪除的函數(shù)或者不可訪問(wèn),則派生類中對(duì)應(yīng)的成員將是被刪除的,原因是編譯器不能使用基類成員來(lái)執(zhí)行派生類對(duì)象基類部分的構(gòu)造、賦值或銷毀操作。
  • 如果在基類中有一個(gè)不可訪問(wèn)或刪除掉的析構(gòu)函數(shù),則派生類中合成的默認(rèn)和拷貝構(gòu)造函數(shù)將是被刪除的,因?yàn)榫幾g器無(wú)法銷毀派生類對(duì)象的基類部分。
  • 和過(guò)一樣,編譯器將不會(huì)合成一個(gè)刪除掉的移動(dòng)操作。 當(dāng)我們使用=default請(qǐng)求一個(gè)移動(dòng)操作時(shí),如果基類中的對(duì)應(yīng)操作是刪除的或不可訪問(wèn)的, 那么派生類中該函數(shù)將是被刪除的, 原因 是派生類對(duì)象的基類部分不可移動(dòng)。 同樣, 如果基類的析構(gòu)函數(shù)是刪除的或不可訪問(wèn)的, 則派生類的移動(dòng)構(gòu)造函數(shù)也將是被刪除的。

派生類的拷貝控制成員

派生類構(gòu)造函數(shù)在其初始化階段中不但要初始化派生類自己的成員,還負(fù)責(zé)初始化派生類對(duì)象的基類部分。因此,派生類的拷貝和移動(dòng)構(gòu)造函數(shù)在拷貝和移動(dòng)自有成員的同時(shí),也要拷貝和移動(dòng)基類部分的成員。類似的,派生類賦值運(yùn)算符也必須為其基類部分的成員賦值。

和構(gòu)造函數(shù)及賦值運(yùn)算符不同的是,析構(gòu)函數(shù)只負(fù)責(zé)銷毀派生類自己分配的資源。對(duì)象的成員是被隱式銷毀的;類似的,派生類對(duì)象的基類部分也是自動(dòng)銷毀的。

對(duì)象銷毀的順序正好與其創(chuàng)建的順序相反:派生類析構(gòu)函數(shù)首先執(zhí)行,然后是基類的析構(gòu)函數(shù),以此類推, 沿著繼承體系的反方向直至最后。

當(dāng)派生類定義了拷貝或移動(dòng)操作時(shí),該操作負(fù)責(zé)拷貝或移動(dòng)包括基類部分成員在內(nèi)的整個(gè)對(duì)象。

定義派生類的拷貝或移動(dòng)構(gòu)造函數(shù)

在默認(rèn)情況下,基類默認(rèn)構(gòu)造函數(shù)初始化派生類對(duì)象的基類部分。如果我們想拷貝(或移動(dòng))基類部分,則必須在派生類的構(gòu)造函數(shù)初始值列表中顯式地使用基類的拷貝(或移動(dòng))構(gòu)造函數(shù)。派生類的賦值運(yùn)算符也必須顯式地為其基類部分賦值。

派生類賦值運(yùn)算符

與拷貝和移動(dòng)構(gòu)造函數(shù)一樣,派生類的賦值運(yùn)算符也必須顯式地為其基類部分賦值。

// Base::operator=(const Base&); 不會(huì)被自動(dòng)調(diào)用D &D::operator=(const D &rhs){Base::operator=(rhs); //為其基類部分賦值//按照過(guò)去的方式為派生類的成員賦值//酌情處理自賦值及釋放已有資源等情況return *this; }

派生類析構(gòu)函數(shù)

如前所述,在析構(gòu)函數(shù)體執(zhí)行完成后,對(duì)象的成員會(huì)被隱式銷毀。類似的,對(duì)象的基類部分也是隱式銷毀的。因此,和構(gòu)造函數(shù)及賦值運(yùn)算符不同的是,派生類析構(gòu)函數(shù)只負(fù)責(zé)銷毀由派生類自己分配的資源。

對(duì)象銷毀的順序正好與其創(chuàng)建的順序相反:派生類析構(gòu)函數(shù)首先執(zhí)行,然后是基類的析構(gòu)函數(shù),以此類推,沿著繼承體系的反方向直至最后。

在構(gòu)造函數(shù)和析構(gòu)函數(shù)中調(diào)用虛函數(shù)

如果構(gòu)造函數(shù)或析構(gòu)函數(shù)調(diào)用了某個(gè)虛函數(shù),則我們應(yīng)該執(zhí)行與構(gòu)造函數(shù)或析構(gòu)函數(shù)所屬類型的虛函數(shù)版本。

測(cè)試類

class TestBase { public:TestBase() { cout << "這是TestBase的構(gòu)造函數(shù)" << endl;fun();cout << endl; }virtual void fun() { cout << "這是TestBase的虛函數(shù)" << endl; }~TestBase() { cout << "這是TestBase的析構(gòu)函數(shù)" << endl; fun();cout << endl;}};class TestDerived:public TestBase { public:TestDerived() { cout << "這是TestDerived的構(gòu)造函數(shù)" << endl;fun();cout << endl;}virtual void fun() { cout << "這是TestDerived的虛函數(shù)" << endl; }~TestDerived() { cout << "這是TestDerived的析構(gòu)函數(shù)" << endl;fun();cout << endl;} };

測(cè)試函數(shù):

void testTestBase() {TestBase tb1;TestDerived td1; }

以上代碼,先創(chuàng)建一個(gè)TestBase的類,故先執(zhí)行TestBase的構(gòu)造函數(shù),然后創(chuàng)建一個(gè)TestDerived的類,由于其繼承了TestBase,故先執(zhí)行TestBase的構(gòu)造函數(shù),然后執(zhí)行TestDerived的構(gòu)造函數(shù),最后當(dāng)testTestBase()函數(shù)執(zhí)行完成后,將td1進(jìn)行析構(gòu),先執(zhí)行TestDerived的析構(gòu)函數(shù),然后執(zhí)行TestBase的析構(gòu)函數(shù),然后將tb1執(zhí)行析構(gòu),即執(zhí)行TestBase的析構(gòu)函數(shù)。在構(gòu)造和析構(gòu)函數(shù)調(diào)用的虛函數(shù),其執(zhí)行與構(gòu)造函數(shù)或析構(gòu)函數(shù)所屬類型的虛函數(shù)版本。

輸出結(jié)果:

這是TestBase的構(gòu)造函數(shù) 這是TestBase的虛函數(shù)這是TestBase的構(gòu)造函數(shù) 這是TestBase的虛函數(shù)這是TestDerived的構(gòu)造函數(shù) 這是TestDerived的虛函數(shù)這是TestDerived的析構(gòu)函數(shù) 這是TestDerived的虛函數(shù)這是TestBase的析構(gòu)函數(shù) 這是TestBase的虛函數(shù)這是TestBase的析構(gòu)函數(shù) 這是TestBase的虛函數(shù)

測(cè)試函數(shù)二:

void testTestBase() {TestDerived td1;TestBase *tb1 = new TestDerived();cout << "調(diào)用fun函數(shù):" << endl;tb1->fun(); //此處調(diào)用的是派生類的fun函數(shù)cout << endl; }

輸出結(jié)果:

這是TestBase的構(gòu)造函數(shù) 這是TestBase的虛函數(shù)這是TestDerived的構(gòu)造函數(shù) 這是TestDerived的虛函數(shù)這是TestBase的構(gòu)造函數(shù) 這是TestBase的虛函數(shù)這是TestDerived的構(gòu)造函數(shù) 這是TestDerived的虛函數(shù)調(diào)用fun函數(shù): 這是TestDerived的虛函數(shù)這是TestDerived的析構(gòu)函數(shù) 這是TestDerived的虛函數(shù)這是TestBase的析構(gòu)函數(shù) 這是TestBase的虛函數(shù)

繼承的構(gòu)造函數(shù)

一個(gè)類只初始化它的直接基類,出于同樣的原因,一個(gè)類也只繼承其直接基類的構(gòu)造函數(shù)。

類不能繼承默認(rèn)、拷貝和移動(dòng)構(gòu)造函數(shù)。如果派生類沒(méi)有直接定義這些構(gòu)造函數(shù),則編譯器將為派生類合成它們。

派生類繼承基類構(gòu)造函數(shù)的方式是提供一條注明了(直接)基類名的using聲明語(yǔ)句。通常情況下,using聲明語(yǔ)句只是令某個(gè)名字在當(dāng)前作用域內(nèi)可見(jiàn),而當(dāng)作用于構(gòu)造函數(shù)時(shí),using聲明語(yǔ)句將令編譯器產(chǎn)生代碼。對(duì)于基類的每個(gè)構(gòu)造函數(shù),編譯器都生成一個(gè)與之對(duì)應(yīng)的派生類構(gòu)造函數(shù)。換句話說(shuō),對(duì)于基類的每個(gè)構(gòu)造函數(shù),編譯器都在派生類中生成一個(gè)形參列表完全相同的構(gòu)造函數(shù)。

繼承的構(gòu)造函數(shù)的特點(diǎn)

和普通成員的using聲明不一樣,一個(gè)構(gòu)造函數(shù)的using聲明不會(huì)改變?cè)摌?gòu)造函數(shù)的訪問(wèn)級(jí)別。例如,不管using聲明出現(xiàn)在哪,基類的私有構(gòu)造函數(shù)在派生類中還是一個(gè)私有構(gòu)造函數(shù),受保護(hù)的構(gòu)造函數(shù)和公有構(gòu)造函數(shù)也是同樣的規(guī)則。

當(dāng)一個(gè)基類構(gòu)造函數(shù)含有默認(rèn)實(shí)參時(shí),這些實(shí)參并不會(huì)被繼承。相反,派生類將獲得多個(gè)繼承的構(gòu)造函數(shù),其中每個(gè)構(gòu)造函數(shù)分別省略掉一個(gè)含有默認(rèn)實(shí)參的形參。

如果基類有多個(gè)構(gòu)造函數(shù),則除了兩個(gè)例外情況,大多數(shù)時(shí)候派生類會(huì)繼承所有這些構(gòu)造函數(shù)。第一個(gè)例外情況是,如果派生類定義的構(gòu)造函數(shù)于基類的構(gòu)造函數(shù)具有相同的參數(shù)列表,則該構(gòu)造函數(shù)將不會(huì)被繼承。定義在派生類中的構(gòu)造函數(shù)將替換繼承而來(lái)的構(gòu)造函數(shù)。

第二個(gè)例外是默認(rèn)、拷貝和移動(dòng)構(gòu)造函數(shù)不會(huì)被繼承。

測(cè)試代碼:

class TestBase { public:TestBase(){ }TestBase(int i):id(i) { }void getId() { cout <<"id:"<<id << endl; }private:int id;};class TestDerived:public TestBase { public:using TestBase::TestBase;};//測(cè)試函數(shù): void testTestBase() {TestDerived td1(5);td1.getId(); }

輸出:

id:5

若將using TestBase::TestBase;注釋掉,則TestDerived td1(5);會(huì)報(bào)錯(cuò)。

容器與繼承

當(dāng)派生類對(duì)象被賦值給基類對(duì)象時(shí),其中的派生類部分將被“切掉”,因此,當(dāng)我們使用容器存放繼承體系中的對(duì)象時(shí),通常必須采取間接存儲(chǔ)的方式。

在容器中放置(智能)指針而非對(duì)象

當(dāng)我們希望在容器中存放具有繼承關(guān)系的對(duì)象時(shí),我們實(shí)際上存放的通常是基類的指針。和往常一樣,這些指針?biāo)笇?duì)象的動(dòng)態(tài)類型可能是基類類型,也可能是派生類類型。

測(cè)試代碼:

class TestBase { public:TestBase(int i):id(i) { }virtual void getId() { cout <<"id:"<<id << endl; }private:int id; };class TestDerived:public TestBase { public:TestDerived(int i,int j) :TestBase(i),num(j) { }virtual void getId() { TestBase::getId();cout << "num:" << num << endl; } private:int num;}; //測(cè)試函數(shù) void testTestBase() {TestBase tb1(1);TestDerived td1(2, 3);vector<shared_ptr<TestBase>>vec;vec.push_back(make_shared<TestBase>(tb1));vec.push_back(make_shared<TestDerived>(td1));for (auto v:vec) {v->getId();cout << "======" << endl;} }

輸出結(jié)果:

id:1 ====== id:2 num:3 ======

編寫(xiě)B(tài)asket類

對(duì)于c++面向?qū)ο蟮木幊虂?lái)說(shuō),我們必須使用指針和引用來(lái)進(jìn)行面向?qū)ο缶幊獭R驗(yàn)橹羔槙?huì)增加程序的復(fù)雜性,所以我們經(jīng)常定義一些輔助的類來(lái)處理這種復(fù)雜情況。

定義一個(gè)表示購(gòu)物籃的類:

decltype的意義

有時(shí)我們希望從表達(dá)式的類型推斷出要定義的變量類型,但是不想用該表達(dá)式的值初始化變量(初始化可以用auto)。為了滿足這一需求,C++11新標(biāo)準(zhǔn)引入了decltype類型說(shuō)明符,它的作用是選擇并返回操作數(shù)的數(shù)據(jù)類型,在此過(guò)程中,編譯器分析表達(dá)式并得到它的類型,卻不實(shí)際計(jì)算表達(dá)式的值。

upper_bound可參考chapter 11

Basket類:

class Basket { public:// Basket使用合成的默認(rèn)構(gòu)造函數(shù)和拷貝控制成員void add_item(const shared_ptr<Quote>&sale){items.insert(sale);}//打印每本書(shū)的總價(jià)和購(gòu)物籃中所有書(shū)的總價(jià)double total_receipt(ostream&)const; private://該函數(shù)用于比較shared_ptr,multiset成員會(huì)用它static bool compare(const shared_ptr<Quote>&lhs, const shared_ptr<Quote>&rhs) {return lhs->isbn() < rhs->isbn();}//multiset保存多個(gè)報(bào)價(jià),按照compare成員排序multiset<shared_ptr<Quote>, decltype(compare)*>items{compare}; };double Basket::total_receipt(ostream&os)const {double sum = 0;for (auto iter = items.cbegin();iter != items.cend();iter=items.upper_bound(*iter)) {sum += print_total(os,**iter,items.count(*iter));}os << "Total Sale: " << sum << endl;return sum; }

Quote類和QuoteDerived類:

class Quote { public:Quote() = default;Quote(const string &book,double sales_price) :bookNo(book),price(sales_price){}string isbn()const { return bookNo; }//返回給定數(shù)量的書(shū)籍的銷售總額//派生類負(fù)責(zé)改寫(xiě)并使用不同的折扣計(jì)算算法virtual double net_price(size_t n)const { return n*price; }virtual ~Quote() = default;//對(duì)析構(gòu)函數(shù)進(jìn)行動(dòng)態(tài)綁定virtual void debug() {cout << "Quote類的bookNo:" << bookNo << ",price: " << price << endl;}virtual ostream & print(ostream &os) {os << "bookNo: " << bookNo << " price: " << price;return os;}private:string bookNo; //書(shū)籍的ISBN編號(hào) protected:double price = 0.0; //代表普通狀態(tài)下不打折的價(jià)格 };double print_total(ostream &os, Quote &qt,int num) {qt.print(os);os << " number: " << num << endl;return qt.net_price(num); }class QuoteDerived :public Quote { public:QuoteDerived() = default;QuoteDerived(const string &book, double sales_price,double d):Quote(book, sales_price),discount(d){}virtual double net_price(size_t cnt) const {return cnt*price*discount;}private:double discount; };

測(cè)試函數(shù):

void testBasket(){Basket bsk;bsk.add_item(make_shared<Quote>("123",60));bsk.add_item(make_shared<QuoteDerived>("123", 60,0.5));bsk.add_item(make_shared<QuoteDerived>("345", 100, 0.5));bsk.add_item(make_shared<Quote>("345", 100));bsk.total_receipt(cout); }

輸出結(jié)果:

bookNo: 123 price: 60 number: 2 bookNo: 345 price: 100 number: 2 Total Sale: 220

若測(cè)試函數(shù)改為:

void testBasket(){Basket bsk;bsk.add_item(make_shared<Quote>("123",60));bsk.add_item(make_shared<QuoteDerived>("123", 60,0.5));bsk.add_item(make_shared<Quote>("345", 100));bsk.add_item(make_shared<QuoteDerived>("345", 100, 0.5));bsk.total_receipt(cout); }

則輸出結(jié)果為:

bookNo: 123 price: 60 number: 2 bookNo: 345 price: 100 number: 2 Total Sale: 320

顯然,結(jié)果不是我們預(yù)期的結(jié)果,我們想要的結(jié)果應(yīng)該是,60+600.5+100+1000.5=240。該程序的結(jié)果是由于其iter=items.upper_bound(*iter) 導(dǎo)致的,因?yàn)樗鼘⑺衖sbn相同的歸為一類,且,按照該類別的第一個(gè)進(jìn)行統(tǒng)一計(jì)算價(jià)錢(qián)。

模擬虛拷貝

在Quote中添加虛函數(shù):

//該虛函數(shù)返回當(dāng)前對(duì)象的一份動(dòng)態(tài)分配的拷貝virtual Quote*clone()const & { return new Quote(*this); }virtual Quote*clone()const && { return new Quote(move(*this)); }

在QuoteDerived中添加虛函數(shù):

virtual QuoteDerived*clone()const & { return new QuoteDerived(*this); }virtual QuoteDerived*clone()const && { return new QuoteDerived(move(*this)); }

改寫(xiě)B(tài)asket類的add_item:

void add_item(const Quote &sale) {items.insert(shared_ptr<Quote>(sale.clone()));}void add_item(const Quote &&sale) {items.insert(shared_ptr<Quote>(move(sale).clone()));}

此時(shí)的測(cè)試函數(shù)為:

void testBasket(){Basket bsk;bsk.add_item(Quote("123",60) );bsk.add_item(QuoteDerived("123", 60,0.5));bsk.add_item(Quote("345", 100));bsk.add_item(QuoteDerived("345", 100, 0.5));bsk.total_receipt(cout); }

總結(jié)

以上是生活随笔為你收集整理的C++ primer 第15章 面向对象程序设计的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

成年人免费看的视频 | 亚洲 欧美 综合 在线 精品 | 五月天丁香视频 | 午夜婷婷在线播放 | 成年人视频免费在线播放 | 久久玖| 黄色大片日本 | 亚洲精品一区二区在线观看 | 国产一区在线播放 | 天天舔天天射天天操 | 久久er99热精品一区二区 | 欧美孕妇视频 | 久草免费手机视频 | 99久热在线精品视频成人一区 | 精品国产精品久久一区免费式 | 欧美xxxx性xxxxx高清 | 国产一区二区免费看 | 国产黄影院色大全免费 | 亚洲精选99 | 亚洲午夜精品久久久久久久久久久久 | 国产97视频在线 | 国产精品欧美一区二区 | 国产剧情一区 | 麻花天美星空视频 | 国产成人av一区二区三区在线观看 | 91av在线免费观看 | 黄色特一级 | 视频一区二区在线观看 | 黄色资源在线 | 国产精品自产拍在线观看蜜 | 亚洲精品视频免费观看 | 国产一区在线播放 | 亚洲综合欧美精品电影 | 日韩在线免费观看视频 | 午夜在线观看影院 | 综合网五月天 | 亚洲色视频 | 一二三区高清 | 亚洲va欧洲va国产va不卡 | 欧美国产日韩一区二区三区 | 午夜婷婷综合 | 97超碰人人在线 | 欧美日本不卡高清 | 亚洲va天堂va欧美ⅴa在线 | 久久艹综合 | 国产成人一区二区三区在线观看 | av线上看 | 婷婷夜夜| 精品国产_亚洲人成在线 | 成片人卡1卡2卡3手机免费看 | 国产一级视屏 | 不卡的av电影在线观看 | 中文字幕亚洲欧美日韩2019 | 日韩免费在线观看视频 | 日本一区二区不卡高清 | 黄色国产在线 | 中文字幕日韩一区二区三区不卡 | 国产不卡精品 | 4hu视频 | 人人爽人人爽人人爽 | 精品日韩在线一区 | 欧美日韩国产精品一区二区 | 成人av一区二区兰花在线播放 | 在线精品一区二区 | 日韩欧美一区二区三区免费观看 | 中文字幕日韩伦理 | av在线专区 | 免费午夜在线视频 | 狠狠干成人 | 九九精品久久 | 狠狠操操网 | 日韩在线观看三区 | www日日 | 亚洲aⅴ在线观看 | 亚洲成aⅴ人在线观看 | a黄色影院| 亚洲va综合va国产va中文 | 亚洲 成人 一区 | 国产亚洲精品福利 | 久久成人亚洲欧美电影 | 国产成人精品999在线观看 | 亚洲黄污 | 91av福利视频| 久久99在线观看 | 97偷拍视频 | 国产尤物在线观看 | 亚洲精品中文在线观看 | 久久久久久久久电影 | 狠狠躁天天躁综合网 | 久久午夜视频 | 999在线视频 | 日韩在线观看你懂的 | 日韩在线免费不卡 | 一区电影| av一区二区在线观看中文字幕 | 久久久久成人精品亚洲国产 | 999久久久免费精品国产 | 黄色成人影院 | 91亚洲精品久久久中文字幕 | 亚洲日韩欧美视频 | 天天艹天天 | 亚洲美女免费精品视频在线观看 | 五月婷婷综合久久 | www.久久色.com| 永久中文字幕 | 黄色日本免费 | a黄色片 | 久草观看| 色婷婷激情电影 | 国产视频网站在线观看 | 亚洲精品综合一区二区 | 成人高清在线 | av成人在线网站 | 亚洲精品综合一区二区 | 99免费国产 | 韩国精品在线观看 | 狠狠色丁香久久婷婷综合丁香 | 亚洲国产精品99久久久久久久久 | 免费91在线 | 午夜电影一区 | 六月激情久久 | 4438全国亚洲精品在线观看视频 | 亚洲狠狠婷婷综合久久久 | 干 操 插| 国产精品久久久久久婷婷天堂 | 青青河边草免费直播 | 成片视频免费观看 | 国产精品美女久久久久久2018 | 国产精品毛片久久久 | 久久精品视频在线观看 | 在线观看视频色 | 国产视频精品视频 | 亚洲综合欧美日韩狠狠色 | 久久a热6 | 日韩三区在线观看 | 成人黄在线观看 | 九九热只有精品 | 国产精品大片免费观看 | 午夜电影中文字幕 | 亚洲欧美精品一区二区 | 狠狠伊人 | 国产高清中文字幕 | 久草在线免费播放 | av不卡在线看 | 黄色毛片一级片 | 成人网页在线免费观看 | 欧美日韩中文视频 | 久久伊人八月婷婷综合激情 | 中文字幕在线免费播放 | 伊人干综合 | 国产精品美女久久久久久久网站 | 狠狠操狠狠干天天操 | 91av视频导航| 91麻豆精品国产自产在线游戏 | 亚洲精品视频免费在线观看 | 特级西西www44高清大胆图片 | 2021国产精品视频 | 黄色亚洲大片免费在线观看 | 国内精品国产三级国产aⅴ久 | 免费在线观看毛片网站 | av在线免费观看不卡 | www.久久99| 欧美一级视频免费看 | 久久久精品国产免费观看一区二区 | 亚洲午夜av久久乱码 | 国产区精品区 | 久操视频在线免费看 | 日本精品久久久久中文字幕 | 婷婷激情av| 超碰在线中文字幕 | 亚洲 欧美 日韩 综合 | 日韩黄色在线 | 国产精品成人在线 | 丁香婷婷亚洲 | 亚洲精品视频久久 | 中文字幕在线观看你懂的 | 91国内产香蕉 | 一二区av | 国产你懂的在线 | 在线国产中文字幕 | 天天射天天干天天操 | 日本久久综合视频 | 天天射天天操天天干 | 91九色视频国产 | 中文字幕在线播放第一页 | 亚洲精品综合欧美二区变态 | 伊人狠狠色丁香婷婷综合 | 午夜婷婷在线观看 | 国产精品无av码在线观看 | 亚洲理论视频 | 国产精品黄色 | 91免费网 | 婷婷色中文网 | 国产黄色片久久 | 免费日韩精品 | 日韩精品一区二区久久 | 日韩激情中文字幕 | 天堂在线一区二区 | 在线国产日韩 | 日韩免费一区二区在线观看 | 爱色av.com| 99草在线视频 | a电影免费看 | 激情丁香婷婷 | 久久男人中文字幕资源站 | 国产色啪| 2023亚洲精品国偷拍自产在线 | 国产一级性生活视频 | 伊人天堂久久 | 亚洲第五色综合网 | 久久欧美精品 | 最新婷婷色 | 日韩免费中文字幕 | 国产精品麻豆99久久久久久 | 欧美一区二区三区在线观看 | 热九九精品 | 中文视频在线 | 全久久久久久久久久久电影 | 亚洲综合五月天 | 国产亚洲综合在线 | 久久9视频 | 久久av网| 国产午夜精品av一区二区 | 爱爱一区 | 狠狠操天天操 | 亚洲国产成人高清精品 | 久久久久久久综合色一本 | а天堂中文最新一区二区三区 | 一区二区亚洲精品 | 久草视频中文在线 | 成人福利在线播放 | 狠狠的操| 久久久午夜电影 | 五月婷婷电影网 | av三级在线看 | 久久激情五月激情 | 成人av.com | 欧美精品久久久久久久久免 | 五月婷婷黄色网 | 日韩一级片网址 | 天天干天天草天天爽 | 成年人电影免费在线观看 | 久草免费在线 | 91福利免费 | 成人动漫视频在线 | 999男人的天堂 | 亚洲在线日韩 | 久久免费视频7 | 久99久精品视频免费观看 | 日韩av免费大片 | 欧美视频二区 | 91av在线免费看 | 国产欧美精品xxxx另类 | 国产一区二区高清不卡 | 久久午夜免费视频 | 久久公开免费视频 | 中文字幕亚洲国产 | 国产黄色特级片 | 国产最新视频在线观看 | 国产精品亚州 | 在线观看免费版高清版 | 日本三级不卡视频 | 日本三级香港三级人妇99 | 亚洲欧洲日韩在线观看 | 中文字幕精品一区二区精品 | 免费网站在线观看成人 | www夜夜| 国内精品久久影院 | 手机色站| 久久中文字幕导航 | 亚洲视频1 | 欧洲视频一区 | 午夜精品一二三区 | 天天干天天操天天拍 | 国产成人一区二区精品非洲 | 在线v| 婷婷在线视频观看 | 伊人午夜| 国产高清区 | av电影一区二区 | 国产精品久久久久久久免费观看 | 色噜噜狠狠色综合中国 | 欧美午夜a | 日韩av免费一区二区 | 高潮久久久久久 | 国产美女精品视频 | 六月激情婷婷 | 久艹视频在线免费观看 | 国精产品999国精产品岳 | 500部大龄熟乱视频使用方法 | 韩国在线一区 | 六月丁香在线视频 | 蜜臀久久99精品久久久无需会员 | 黄色一级性片 | 欧洲精品久久久久毛片完整版 | 色综合中文综合网 | 久久久久免费精品国产小说色大师 | 国产精品成人一区二区三区吃奶 | 日本爱爱片 | 香蕉视频在线免费 | 麻豆精品视频在线 | 狠狠地日 | 亚洲码国产日韩欧美高潮在线播放 | 麻豆视频网址 | 91精品秘密在线观看 | 久久精品国产久精国产 | 五月天国产 | 成人全视频免费观看在线看 | 超碰在线色 | 国产一级精品在线观看 | 天天爱天天 | 亚洲年轻女教师毛茸茸 | 午夜久久视频 | 狠狠色丁香婷婷综合久小说久 | 麻豆视频在线免费观看 | 国精产品999国精产 久久久久 | 婷婷在线视频 | 久久五月婷婷丁香 | 久久精品观看 | 毛片基地黄久久久久久天堂 | 日韩一区二区三 | 99热精品在线观看 | 欧洲黄色片 | 中文字幕av免费 | 日韩理论在线播放 | 久久精品99久久久久久2456 | 深爱激情婷婷网 | 黄色国产精品 | 欧美日韩一区二区三区不卡 | 波多野结衣电影一区二区三区 | 欧美日韩另类在线观看 | 天天干天天草天天爽 | 亚洲精品综合久久 | 久久av伊人 | 国产天天爽 | 亚洲国产视频在线 | 婷婷激情综合五月天 | a午夜在线 | 欧美一区二区三区不卡 | www免费在线观看 | av电影一区二区三区 | 国产成人一区二区三区在线观看 | 人人舔人人插 | 手机看片国产日韩 | 国产激情电影综合在线看 | 久久久久久久免费 | 亚洲少妇自拍 | 欧美一级性 | av爱干 | 99视频在线免费看 | 久久高视频 | 中文字幕无吗 | 亚洲情婷婷 | 天天综合网久久 | 日韩欧美一区二区在线 | 97超碰资源网 | 国产精品12345 | 97免费在线视频 | 韩国av在线播放 | 国产午夜精品一区二区三区 | 美女视频黄是免费的 | 福利一区二区在线 | 国产又粗又猛又黄视频 | 人人舔人人舔 | 国产四虎在线 | 96精品高清视频在线观看软件特色 | 人人干狠狠操 | 亚洲国产网站 | 911免费视频 | bayu135国产精品视频 | 成人日批视频 | 91探花国产综合在线精品 | 欧美成人精品欧美一级乱黄 | 国产中文字幕一区 | 国产麻豆果冻传媒在线观看 | 免费国产亚洲视频 | 四虎影视8848dvd | 国产精品国内免费一区二区三区 | 欧美日韩一区二区在线 | 久久久免费精品视频 | 天天操天天添天天吹 | 狠狠操欧美 | 少妇自拍av | 国产美女精彩久久 | 超碰个人在线 | 日本精品视频在线观看 | 96精品高清视频在线观看软件特色 | 欧美三级高清 | 中文字幕电影一区 | 欧美精品在线观看免费 | 黄色小说视频在线 | 成人av网址大全 | 成人黄色视 | 五月婷婷中文网 | 国产999精品久久久久久麻豆 | 精品国偷自产国产一区 | 欧美黄色成人 | 午夜精品久久久久久久99 | 欧美成人精品三级在线观看播放 | 亚洲精品在线观看不卡 | 久久国语| 日韩欧美在线高清 | 8090yy亚洲精品久久 | 黄色动态图xx | 最新免费中文字幕 | 久久久久久久久国产 | 六月色婷婷 | 亚洲精品国偷自产在线91正片 | 伊人电影天堂 | 国产精品久久久久久久久久免费看 | 亚洲视频综合在线 | 婷婷精品视频 | 国产福利不卡视频 | 四虎成人精品在永久免费 | 精品中文字幕在线播放 | 国产高清视频网 | 一区二区三区久久 | 欧美日韩电影在线播放 | 国产精品丝袜 | 中文字幕在线观看视频免费 | 黄色日本免费 | 久久免费看a级毛毛片 | 在线观看久草 | 4hu视频 | 波多野结衣视频一区 | 久久综合在线 | 99在线看| 日韩高清久久 | 成人免费视频在线观看 | 香蕉成人在线视频 | 午夜av一区 | 在线电影91 | 精品国自产在线观看 | 国产精品都在这里 | 国产三级国产精品国产专区50 | 欧美精品黑人性xxxx | 亚洲精品中文字幕在线观看 | 91天天操 | 免费91麻豆精品国产自产在线观看 | 亚洲一区视频免费观看 | 婷婷爱五月天 | 日韩免费在线观看视频 | 亚洲国产成人精品电影在线观看 | 91资源在线视频 | 欧美精品做受xxx性少妇 | 日韩欧美极品 | 亚洲成人一二三 | 九九九热精品免费视频观看网站 | 免费日韩一区二区三区 | 国产精品免费久久久久久久久久中文 | 亚洲欧美在线综合 | 欧美精品xxx | 日韩精品专区在线影院重磅 | 国产精品久久久久亚洲影视 | 91人人在线 | 日韩欧美一区二区在线 | 国产91在线免费视频 | 开心色激情网 | 日韩av影视在线观看 | 天天天插 | 亚洲码国产日韩欧美高潮在线播放 | 人人爽人人插 | 国产一级黄色av | 亚洲精品美女在线观看 | 手机看片午夜 | 一区二区三区日韩精品 | 日女人免费视频 | 黄色免费观看网址 | 六月婷婷网 | 精品久久久一区二区 | 高清国产在线一区 | 久久 一区 | 日韩在线观看第一页 | 日日精品 | 国产高清精品在线 | 国内精品在线看 | av不卡中文| a成人v在线 | 国产精品免费大片视频 | 日韩av一区二区在线 | 97av免费视频 | 欧美小视频在线观看 | 中文永久字幕 | 韩国av免费在线观看 | wwwwww国产 | 亚洲 欧美 国产 va在线影院 | www五月婷婷 | 97超碰在| 青草视频在线播放 | 四虎影视成人精品 | 国产精品成人一区二区 | 99精品视频一区 | 日韩视频图片 | 久久精品视频免费 | 国产一级h | 国产成免费视频 | 亚洲视频一级 | 天天躁日日躁狠狠躁av中文 | 色国产精品一区在线观看 | 五月天婷亚洲天综合网精品偷 | 国产91亚洲 | 国产午夜精品一区二区三区嫩草 | 手机在线中文字幕 | 正在播放国产一区 | 成人一级免费视频 | 日韩免费在线视频观看 | 九九亚洲视频 | 在线观看av大片 | av黄色国产 | 在线v片免费观看视频 | 国产麻豆电影 | 97在线视频免费 | 欧美激情第一区 | 又黄又爽的视频在线观看网站 | 高潮久久久久久久久 | 在线看片一区 | 夜夜爽天天爽 | 人人精品 | 国产传媒一区在线 | 麻豆视频大全 | 九九激情视频 | 这里有精品在线视频 | 日韩精品欧美精品 | 精品美女国产在线 | 免费看黄在线网站 | 亚洲国产精品一区二区久久,亚洲午夜 | 97超碰人人网 | 日本精品久久久久影院 | 免费在线91 | 99精品久久精品一区二区 | 国产在线精品一区二区 | 亚洲最新在线视频 | 免费av在线| 日本中文一级片 | 狠狠干综合网 | 久久玖 | 一级精品视频在线观看宜春院 | 日本系列中文字幕 | 麻豆视频免费入口 | 国产在线观看xxx | 中文资源在线播放 | 永久免费精品视频网站 | 国产成人性色生活片 | 狠狠干.com | 高清av在线免费观看 | 午夜av免费| 美女视频一区 | 国产一区自拍视频 | 国产中文字幕免费 | av网址aaa| 国产精品入口传媒 | 成人观看 | 国产精品都在这里 | 欧美一区二区视频97 | 在线观看成人一级片 | 亚洲 精品在线视频 | 亚洲精品国偷拍自产在线观看蜜桃 | 欧美日韩另类视频 | 99资源网| 久久精品电影网 | 日韩免费视频播放 | 亚洲色图 校园春色 | 91免费看黄| 亚洲国产字幕 | 黄色网www | 欧美日韩国产三级 | 999抗病毒口服液 | 国产精品尤物 | 午夜婷婷在线观看 | av女优中文字幕在线观看 | 亚洲国产视频直播 | 高清av网站 | 日日弄天天弄美女bbbb | 国产精品久久久久久久毛片 | 欧美日韩视频 | 欧洲精品亚洲精品 | 99色在线视频 | 夜夜躁狠狠躁日日躁视频黑人 | 日本中文字幕在线观看 | 日韩在线欧美在线 | 国产视频观看 | www.五月天婷婷 | 久久精品香蕉视频 | 精品国产乱码久久久久久浪潮 | 国产精品 日韩 欧美 | 成人香蕉视频 | 在线一二三区 | 成人精品福利 | 韩国av免费看 | 91av视频在线免费观看 | 国产精彩视频一区二区 | 国产玖玖精品视频 | 九九在线高清精品视频 | 成全在线视频免费观看 | 丁香激情综合 | 99精品久久久久久久久久综合 | 中文字幕一区三区 | 中文字幕日韩av | 精品一区二区久久久久久久网站 | 欧美福利久久 | 黄色片免费电影 | 亚洲天堂va | 91手机视频| 日本一区二区高清不卡 | 一区中文字幕电影 | av成人动漫在线观看 | 久久综合9988久久爱 | 精品亚洲免费视频 | 亚洲午夜久久久久久久久久久 | 精品国产美女在线 | 激情五月亚洲 | 96久久| 丁香六月天 | 国产黄色美女 | 久草在线视频资源 | 99免费国产| 超碰免费公开 | 国产乱码精品一区二区三区介绍 | 日韩欧美视频二区 | 国产在线精品视频 | 亚洲永久精品视频 | 国产精品久久久久久久久久新婚 | 四虎免费在线观看视频 | 香蕉视频在线观看免费 | 天天干天天做 | 中文字幕免费播放 | 日本在线观看一区 | 国产成人久久精品亚洲 | 色爽网站 | 在线免费国产视频 | 国产精品久久久久久久久搜平片 | www在线免费观看 | 亚洲精品国产精品99久久 | 一区二区三区四区免费视频 | 特级aaa毛片| 久久精品视频免费观看 | 亚洲精品乱码久久久久久蜜桃91 | 97国产一区| 日韩av高清 | 国产福利a | 91片黄在线观看动漫 | 久久色亚洲 | 欧美成人精品三级在线观看播放 | 97精品国产91久久久久久久 | 狠狠干夜夜操天天爽 | 伊人小视频 | 激情网站免费观看 | 日韩国产精品毛片 | 在线成人看片 | 国产无套精品久久久久久 | 安徽妇搡bbbb搡bbbb | 久久天堂精品视频 | 久久艹精品 | 日日夜夜亚洲 | 国产一区视频在线播放 | 久久精品国产一区二区三区 | 日韩欧美大片免费观看 | 激情偷乱人伦小说视频在线观看 | 亚洲精品午夜久久久久久久 | 婷婷丁香色 | 高清免费在线视频 | 欧美a免费| 国产视频亚洲 | 狠狠操综合 | 精品人人爽| 中午字幕在线 | 热久在线 | 一区二区av| 色综合久久88色综合天天6 | 欧美综合色在线图区 | 在线免费观看欧美日韩 | 在线观看视频一区二区三区 | 97在线观看免费观看高清 | 中国一级特黄毛片大片久久 | 成人欧美亚洲 | 日日干夜夜操视频 | 91精品国自产拍天天拍 | 青草视频网 | 一区二区三区免费在线播放 | 天天操天 | 日韩成人不卡 | 国产在线观看免 | 色综合久久88色综合天天人守婷 | 97超碰国产精品 | 国产精品美女久久久久久久久 | 久久天天躁夜夜躁狠狠85麻豆 | 亚洲精品日韩在线观看 | 免费观看一级视频 | www.香蕉 | 欧美另类交在线观看 | 五月婷婷开心中文字幕 | 日韩精品免费在线 | 成人av在线电影 | 美女av免费| www.狠狠插.com| a在线免费 | 久久永久免费视频 | 麻豆成人在线观看 | 天天天综合 | 久久99精品国产91久久来源 | 91理论片午午伦夜理片久久 | 日本免费久久高清视频 | 九九导航 | 韩国av免费在线观看 | 日韩系列 | 99热这里只有精品1 av中文字幕日韩 | 国产拍在线 | 99精品国产99久久久久久福利 | 99久久99视频 | av丝袜天堂 | 日韩欧美一二三 | 国产又粗又硬又爽视频 | 伊人色综合久久天天网 | 最近免费中文字幕mv在线视频3 | 日韩理论影院 | 欧美日韩亚洲在线 | 五月天久久综合 | 少妇性aaaaaaaaa视频 | 97网在线观看 | 国内精品久久久久久久97牛牛 | 色婷婷色 | 一区二区精品在线观看 | 免费在线电影网址大全 | 国产在线精品一区二区不卡了 | 亚洲mv大片欧洲mv大片免费 | 在线亚州| 国产精品24小时在线观看 | 国产亚洲资源 | 日韩av资源在线观看 | 久久久久久久久久伊人 | 免费精品国产va自在自线 | 在线中文字幕网站 | 超碰999| 国产分类视频 | 激情五月激情综合网 | 精品国产一区二区三区四 | 91精品国产福利在线观看 | 成人污视频在线观看 | 亚洲第一香蕉视频 | 久久综合成人 | 国产精品18久久久久久久网站 | 97在线视频免费观看 | 久久久久伦理电影 | 久久伊人综合 | 亚洲成人软件 | 毛片在线网 | 天天射天天色天天干 | 成人丝袜| 欧美成人黄色 | 亚洲高清91 | 成人av影视 | 免费a级毛片在线看 | 99久久精品免费看国产 | 五月婷婷丁香 | 日韩精品一二三 | 国产日韩欧美在线观看视频 | 狠狠操夜夜操 | 国产精品久久久久久久婷婷 | 日韩免费看的电影 | 久久精品第一页 | 国产精品久久久久av福利动漫 | 精品一区精品二区高清 | 日韩欧美视频在线 | 国内视频 | 干天天 | 丰满少妇高潮在线观看 | 久久久久久久久久福利 | 一区二区三区日韩在线观看 | 国产亚洲精品久久久久秋 | 97成人在线观看 | 黄色美女免费网站 | 久草在线视频在线观看 | 波多野结衣亚洲一区二区 | 女人18精品一区二区三区 | 亚洲欧洲xxxx | 亚洲精品一区二区三区在线观看 | 国产亚洲精品成人 | 特级黄色片免费看 | 婷婷六月综合亚洲 | 免费能看的黄色片 | 天天操夜夜操夜夜操 | 久久成人国产精品入口 | 天天爽夜夜爽人人爽一区二区 | 国产精品扒开做爽爽的视频 | 又黄又刺激视频 | 国产免费激情久久 | 天天干夜夜擦 | 欧美国产日韩一区二区 | 日韩欧美xxxx | 九九热免费视频在线观看 | 免费看片网页 | 天天操操操操操 | 久久99热久久99精品 | 国产在线第三页 | 91av视频观看| 成人国产在线 | 亚洲国产理论片 | a级国产乱理伦片在线播放 久久久久国产精品一区 | 成人国产精品免费 | 国产在线欧美日韩 | 国产精品免费麻豆入口 | 特级毛片在线免费观看 | 天天做日日做天天爽视频免费 | 日韩精品视频在线观看免费 | 久久免费福利 | 国产精品涩涩屋www在线观看 | 久久精品99国产国产 | 久草香蕉在线视频 | 日本性生活一级片 | 一区二区精品在线 | 色人久久 | 91精品视频免费看 | 久久久国产精品一区二区三区 | 狠狠色狠狠色综合系列 | 香蕉免费 | 欧美精品一区二区在线播放 | av视屏在线| av3级在线| 亚洲精品在线观看免费 | 免费黄色a网站 | 九九久久国产精品 | 久久久精品一区二区三区 | 婷婷色综合网 | 女人18片毛片90分钟 | 麻豆国产精品视频 | 二区三区在线观看 | 亚洲成a人片在线观看中文 中文字幕在线视频第一页 狠狠色丁香婷婷综合 | 色婷婷骚婷婷 | av在线网站大全 | 久草精品视频 | 一级特黄av | 在线v | 狠狠狠色丁香婷婷综合久久88 | www日 | 色婷婷免费 | 成人午夜剧场在线观看 | 精品日韩视频 | 日本中文字幕在线观看 | 免费在线观看av网址 | 国产不卡精品视频 | 亚洲一区二区三区毛片 | av黄色免费看 | 国产精品理论视频 | 中文字幕在线免费 | 天天草天天干天天 | 久久99免费 | 97理论电影 | 国产精品99久久免费黑人 | 国产麻豆剧果冻传媒视频播放量 | 久99久中文字幕在线 | 日韩专区在线 | 黄色一级在线视频 | 成人欧美一区二区三区黑人麻豆 | 五月天激情在线 | 人人射人人澡 | 亚洲综合成人在线 | 亚洲清纯国产 | 国产高清视频免费观看 | 在线黄色观看 | 一区二区三区免费在线 | 免费h在线观看 | 久久热首页 | 国产色爽 | av免费观看高清 | 五月婷婷操 | 又粗又长又大又爽又黄少妇毛片 | 日本精a在线观看 | 国产福利一区二区在线 | 成人精品亚洲 | 国产一区二区三区高清播放 | 91av原创| 亚洲一区久久久 | 天天曰天天射 | 国产视频2| 精品国产成人在线影院 | 日韩毛片精品 | 国产九色视频在线观看 | 久久久在线观看 | 亚洲国产一区在线观看 | 成人免费 在线播放 | av一本久道久久波多野结衣 | 婷婷综合亚洲 | 免费看一级一片 | 四虎永久免费网站 | 日韩欧美视频在线观看免费 | 日日碰狠狠添天天爽超碰97久久 | 国产精品综合久久久 | av在线一级 | 国产中文字幕一区二区三区 | 成人动漫一区二区 | 一区二区三区电影 | 中文在线字幕观看电影 | 日日干夜夜操视频 | 91视频高清 | 精品视频免费播放 | 97福利在线观看 | 国产一区欧美一区 | 我要看黄色一级片 | 91高清视频 | 99热只有精品在线观看 | 中文字幕在线观看第一区 | 91看片黄色| 超碰在线官网 | 亚洲精品在线免费 | 日本在线观看中文字幕无线观看 | 中文字幕在线观看一区 | 亚洲精品视频二区 | 亚洲国产精品激情在线观看 | 久久久久区 | 欧美性色网站 | 激情文学综合丁香 | 国产一区二区在线影院 | 国产精品女同一区二区三区久久夜 | 日韩首页 | 国产剧在线观看片 | 天天色天天骑天天射 | 亚洲午夜精品一区 | 亚洲国产影院av久久久久 | 天天爱天天草 | 亚洲涩涩涩 | www日韩高清 | 视频在线观看亚洲 | 三级av在线 | 国产色爽| 午夜国产福利在线观看 | 91视频麻豆 | 免费高清在线观看成人 | 中文字幕的| 亚洲一级免费观看 | 亚洲激情 欧美激情 | 国产在线视频一区二区三区 | 国产又粗又猛又黄又爽的视频 | 久久艹国产视频 | 亚洲欧美国产日韩在线观看 | 国内精品久久久久久久久久清纯 | 欧美日韩中文字幕综合视频 | 天天操夜夜爱 | 中文字幕一区二区三区四区视频 | 国产免费视频一区二区裸体 | 亚洲在线资源 | 国产精品久久人 | 成人国产一区 | 最近2019中文免费高清视频观看www99 | 黄色中文字幕 | 在线高清av | 在线观看久久久久久 | 91网在线看 | 天天操天天干天天摸 | 亚洲一级国产 | 在线观看视频一区二区三区 | 成年人免费在线播放 | 国产精品久久久久久五月尺 | 黄色资源在线 | 久草电影免费在线观看 | 99精品一区| 一本一道久久a久久精品 | 91久久在线观看 | 91成人在线免费观看 | 欧美va天堂va视频va在线 | 韩国精品福利一区二区三区 | 特级毛片网 | 国产精品美女久久久久久 | 免费无遮挡动漫网站 | 国产视频精品免费 | 久草久草久草久草 | 成人免费看片98欧美 | 午夜丁香网 | 国色天香永久免费 | 午夜黄色一级片 | 91成人破解版 | 欧洲在线免费视频 | 亚洲国产精品成人va在线观看 | 婷婷av网| 视频在线观看一区 | 欧美贵妇性狂欢 | 国产女人40精品一区毛片视频 | 婷婷色在线视频 | 午夜三级毛片 | 国产流白浆高潮在线观看 | 欧美a级片免费看 | 日韩性色 | 激情久久伊人 | 天天干,天天射,天天操,天天摸 | 中文在线资源 | 麻豆影视网站 | 亚洲精品在线观看网站 | 国产视频 亚洲精品 | 亚洲国产精品一区二区久久,亚洲午夜 | a级片久久久 | 国产大陆亚洲精品国产 | 蜜臀久久99静品久久久久久 | 久久成人国产精品免费软件 | 国产福利一区二区在线 | 超碰在线98 | 国产999| 欧美天天综合网 | 欧美日韩三级在线观看 | 午夜黄色影院 |