欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

解析C++編程中virtual聲明的虛函數(shù)以及單個(gè)繼承

 更新時(shí)間:2016年01月22日 15:02:50   投稿:goldensun  
這篇文章主要介紹了C++編程中virtual聲明的虛函數(shù)以及單個(gè)繼承,剖析虛函數(shù)和單個(gè)基類(lèi)所能夠繼承的成員,要的朋友可以參考下

虛函數(shù)

虛函數(shù)是應(yīng)在派生類(lèi)中重新定義的成員函數(shù)。 當(dāng)使用指針或?qū)?lèi)的引用來(lái)引用派生的類(lèi)對(duì)象時(shí),可以為該對(duì)象調(diào)用虛函數(shù)并執(zhí)行該函數(shù)的派生類(lèi)版本。
虛函數(shù)確保為該對(duì)象調(diào)用正確的函數(shù),這與用于進(jìn)行函數(shù)調(diào)用的表達(dá)式無(wú)關(guān)。
假定基類(lèi)包含聲明為 virtual 的函數(shù),并且派生類(lèi)定義了相同的函數(shù)。 為派生類(lèi)的對(duì)象調(diào)用派生類(lèi)中的函數(shù),即使它是使用指針或?qū)?lèi)的引用來(lái)調(diào)用的。 以下示例顯示了一個(gè)基類(lèi),它提供了 PrintBalance 函數(shù)和兩個(gè)派生類(lèi)的實(shí)現(xiàn)

// deriv_VirtualFunctions.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;

class Account {
public:
  Account( double d ) { _balance = d; }
  virtual double GetBalance() { return _balance; }
  virtual void PrintBalance() { cerr << "Error. Balance not available for base type." << endl; }
private:
  double _balance;
};

class CheckingAccount : public Account {
public:
  CheckingAccount(double d) : Account(d) {}
  void PrintBalance() { cout << "Checking account balance: " << GetBalance() << endl; }
};

class SavingsAccount : public Account {
public:
  SavingsAccount(double d) : Account(d) {}
  void PrintBalance() { cout << "Savings account balance: " << GetBalance(); }
};

int main() {
  // Create objects of type CheckingAccount and SavingsAccount.
  CheckingAccount *pChecking = new CheckingAccount( 100.00 ) ;
  SavingsAccount *pSavings = new SavingsAccount( 1000.00 );

  // Call PrintBalance using a pointer to Account.
  Account *pAccount = pChecking;
  pAccount->PrintBalance();

  // Call PrintBalance using a pointer to Account.
  pAccount = pSavings;
  pAccount->PrintBalance();  
}

在前面的代碼中,對(duì) PrintBalance 的調(diào)用是相同的,pAccount 所指向的對(duì)象除外。 由于 PrintBalance 是虛擬的,因此將調(diào)用為每個(gè)對(duì)象定義的函數(shù)版本。 派生類(lèi) PrintBalance 和 CheckingAccount 中的 SavingsAccount 函數(shù)“重寫(xiě)”基類(lèi) Account 中的函數(shù)。
如果聲明的類(lèi)不提供 PrintBalance 函數(shù)的重寫(xiě)實(shí)現(xiàn),則使用基類(lèi) Account 中的默認(rèn)實(shí)現(xiàn)。
派生類(lèi)中的函數(shù)僅在基類(lèi)中的虛函數(shù)的類(lèi)型相同時(shí)重寫(xiě)這些虛函數(shù)。 派生類(lèi)中的函數(shù)不能只是與其返回類(lèi)型中的基類(lèi)的虛函數(shù)不同;參數(shù)列表也必須不同。
當(dāng)使用指針或引用調(diào)用函數(shù)時(shí),以下規(guī)則將適用:
根據(jù)為其調(diào)用的對(duì)象的基本類(lèi)型來(lái)解析對(duì)虛函數(shù)的調(diào)用。
根據(jù)指針或引用的類(lèi)型來(lái)解析對(duì)非虛函數(shù)的調(diào)用。
以下示例說(shuō)明在通過(guò)指針調(diào)用時(shí)虛函數(shù)和非虛函數(shù)的行為:

// deriv_VirtualFunctions2.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;

class Base {
public:
  virtual void NameOf();  // Virtual function.
  void InvokingClass();  // Nonvirtual function.
};

// Implement the two functions.
void Base::NameOf() {
  cout << "Base::NameOf\n";
}

void Base::InvokingClass() {
  cout << "Invoked by Base\n";
}

class Derived : public Base {
public:
  void NameOf();  // Virtual function.
  void InvokingClass();  // Nonvirtual function.
};

// Implement the two functions.
void Derived::NameOf() {
  cout << "Derived::NameOf\n";
}

void Derived::InvokingClass() {
  cout << "Invoked by Derived\n";
}

int main() {
  // Declare an object of type Derived.
  Derived aDerived;

  // Declare two pointers, one of type Derived * and the other
  // of type Base *, and initialize them to point to aDerived.
  Derived *pDerived = &aDerived;
  Base  *pBase  = &aDerived;

  // Call the functions.
  pBase->NameOf();      // Call virtual function.
  pBase->InvokingClass();  // Call nonvirtual function.
  pDerived->NameOf();    // Call virtual function.
  pDerived->InvokingClass(); // Call nonvirtual function.
}

輸出

Derived::NameOf
Invoked by Base
Derived::NameOf
Invoked by Derived

請(qǐng)注意,無(wú)論 NameOf 函數(shù)是通過(guò)指向 Base 的指針還是通過(guò)指向 Derived 的指針進(jìn)行調(diào)用,它都會(huì)調(diào)用 Derived 的函數(shù)。 它調(diào)用 Derived 的函數(shù),因?yàn)?NameOf 是虛函數(shù),并且 pBase 和 pDerived 都指向類(lèi)型 Derived 的對(duì)象。
由于僅為類(lèi)類(lèi)型的對(duì)象調(diào)用虛函數(shù),因此不能將全局函數(shù)或靜態(tài)函數(shù)聲明為 virtual。
在派生類(lèi)中聲明重寫(xiě)函數(shù)時(shí)可使用 virtual 關(guān)鍵字,但它不是必需的;虛函數(shù)的重寫(xiě)始終是虛擬的。
必須定義基類(lèi)中的虛函數(shù),除非使用 pure-specifier 聲明它們。 (有關(guān)純虛函數(shù)的詳細(xì)信息,請(qǐng)參閱抽象類(lèi)。)
可通過(guò)使用范圍解析運(yùn)算符 (::) 顯式限定函數(shù)名稱(chēng)來(lái)禁用虛函數(shù)調(diào)用機(jī)制。 考慮先前涉及 Account 類(lèi)的示例。 若要調(diào)用基類(lèi)中的 PrintBalance,請(qǐng)使用如下所示的代碼:

CheckingAccount *pChecking = new CheckingAccount( 100.00 );

pChecking->Account::PrintBalance(); // Explicit qualification.

Account *pAccount = pChecking; // Call Account::PrintBalance

pAccount->Account::PrintBalance();  // Explicit qualification.

在前面的示例中,對(duì) PrintBalance 的調(diào)用將禁用虛函數(shù)調(diào)用機(jī)制。


單個(gè)繼承
在“單繼承”(繼承的常見(jiàn)形式)中,類(lèi)僅具有一個(gè)基類(lèi)。考慮下圖中闡釋的關(guān)系。

2016122145736303.jpeg (121×102)

簡(jiǎn)單單繼承關(guān)系圖
注意該圖中從常規(guī)到特定的進(jìn)度。在大多數(shù)類(lèi)層次結(jié)構(gòu)的設(shè)計(jì)中發(fā)現(xiàn)的另一個(gè)常見(jiàn)特性是,派生類(lèi)與基類(lèi)具有“某種”關(guān)系。在該圖中,Book 是一種 PrintedDocument,而 PaperbackBook 是一種 book。
該圖中的另一個(gè)要注意的是:Book 既是派生類(lèi)(來(lái)自 PrintedDocument),又是基類(lèi)(PaperbackBook 派生自 Book)。此類(lèi)類(lèi)層次結(jié)構(gòu)的框架聲明如下面的示例所示:

// deriv_SingleInheritance.cpp
// compile with: /LD
class PrintedDocument {};

// Book is derived from PrintedDocument.
class Book : public PrintedDocument {};

// PaperbackBook is derived from Book.
class PaperbackBook : public Book {};

PrintedDocument 被視為 Book 的“直接基”類(lèi);它是 PaperbackBook 的“間接基”類(lèi)。差異在于,直接基類(lèi)出現(xiàn)在類(lèi)聲明的基礎(chǔ)列表中,而間接基類(lèi)不是這樣的。
在聲明派生的類(lèi)之前聲明從中派生每個(gè)類(lèi)的基類(lèi)。為基類(lèi)提供前向引用聲明是不夠的;它必須是一個(gè)完整聲明。
在前面的示例中,使用訪(fǎng)問(wèn)說(shuō)明符 public。 成員訪(fǎng)問(wèn)控制中介紹了公共的、受保護(hù)的和私有的繼承的含義。
類(lèi)可用作多個(gè)特定類(lèi)的基類(lèi),如下圖所示。

2016122145806415.jpeg (486×156)

注意
有向非循環(huán)圖對(duì)于單繼承不是唯一的。它們還用于表示多重繼承關(guān)系圖。 多重繼承中對(duì)本主題進(jìn)行了說(shuō)明。
在繼承中,派生類(lèi)包含基類(lèi)的成員以及您添加的所有新成員。因此,派生類(lèi)可以引用基類(lèi)的成員(除非在派生類(lèi)中重新定義這些成員)。當(dāng)在派生類(lèi)中重新定義了直接或間接基類(lèi)的成員時(shí),范圍解析運(yùn)算符 (::) 可用于引用這些成員。請(qǐng)看以下示例:

// deriv_SingleInheritance2.cpp
// compile with: /EHsc /c
#include <iostream>
using namespace std;
class Document {
public:
  char *Name;  // Document name.
  void PrintNameOf();  // Print name.
};

// Implementation of PrintNameOf function from class Document.
void Document::PrintNameOf() {
  cout << Name << endl;
}

class Book : public Document {
public:
  Book( char *name, long pagecount );
private:
  long PageCount;
};

// Constructor from class Book.
Book::Book( char *name, long pagecount ) {
  Name = new char[ strlen( name ) + 1 ];
  strcpy_s( Name, strlen(Name), name );
  PageCount = pagecount;
};

請(qǐng)注意,Book 的構(gòu)造函數(shù) (Book::Book) 具有對(duì)數(shù)據(jù)成員 Name 的訪(fǎng)問(wèn)權(quán)。在程序中,可以創(chuàng)建和使用類(lèi)型為 Book 的對(duì)象,如下所示:

// Create a new object of type Book. This invokes the
//  constructor Book::Book.
Book LibraryBook( "Programming Windows, 2nd Ed", 944 );

...

// Use PrintNameOf function inherited from class Document.
LibraryBook.PrintNameOf();

如前面的示例所示,以相同的方式使用類(lèi)成員和繼承的數(shù)據(jù)和函數(shù)。如果類(lèi) Book 的實(shí)現(xiàn)調(diào)用 PrintNameOf 函數(shù)的重新實(shí)現(xiàn),則只能通過(guò)使用范圍解析 (Document) 運(yùn)算符來(lái)調(diào)用屬于 :: 類(lèi)的函數(shù):

// deriv_SingleInheritance3.cpp
// compile with: /EHsc /LD
#include <iostream>
using namespace std;

class Document {
public:
  char *Name;     // Document name.
  void PrintNameOf() {} // Print name.
};

class Book : public Document {
  Book( char *name, long pagecount );
  void PrintNameOf();
  long PageCount;
};

void Book::PrintNameOf() {
  cout << "Name of book: ";
  Document::PrintNameOf();
}

如果存在可訪(fǎng)問(wèn)的明確基類(lèi),則可以隱式將派生類(lèi)的指針和引用轉(zhuǎn)換為其基類(lèi)的指針和引用。下面的代碼使用指針演示了此概念(相同的原則適用于引用):

// deriv_SingleInheritance4.cpp
// compile with: /W3
struct Document {
  char *Name;
  void PrintNameOf() {}
};

class PaperbackBook : public Document {};

int main() {
  Document * DocLib[10];  // Library of ten documents.
  for (int i = 0 ; i < 10 ; i++)
   DocLib[i] = new Document;
}

在前面的示例中,創(chuàng)建了不同的類(lèi)型。但是,由于這些類(lèi)型都派生自 Document 類(lèi),因此存在對(duì) Document * 的隱式轉(zhuǎn)換。因此,DocLib 是“異類(lèi)列表”(其中包含的所有對(duì)象并非屬于同一類(lèi)型),該列表包含不同類(lèi)型的對(duì)象。
由于 Document 類(lèi)具有一個(gè) PrintNameOf 函數(shù),因此它可以打印庫(kù)中每本書(shū)的名稱(chēng),但它可能會(huì)忽略某些特定于文檔類(lèi)型的信息(Book 的頁(yè)計(jì)數(shù)、HelpFile 的字節(jié)數(shù)等)。
注意
強(qiáng)制使用基類(lèi)來(lái)實(shí)現(xiàn)函數(shù)(如 PrintNameOf)通常不是最佳設(shè)計(jì)。 虛函數(shù)提供其他設(shè)計(jì)替代方法。


相關(guān)文章

  • C++實(shí)現(xiàn)簡(jiǎn)單版通訊錄管理系統(tǒng)

    C++實(shí)現(xiàn)簡(jiǎn)單版通訊錄管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)簡(jiǎn)單版通訊錄管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • C語(yǔ)言動(dòng)態(tài)內(nèi)存分配圖文講解

    C語(yǔ)言動(dòng)態(tài)內(nèi)存分配圖文講解

    給數(shù)組分配多大的空間?你是否和初學(xué)C時(shí)的我一樣,有過(guò)這樣的疑問(wèn)。這一期就來(lái)聊一聊動(dòng)態(tài)內(nèi)存的分配,讀完這篇文章,你可能對(duì)內(nèi)存的分配有一個(gè)更好的理解
    2023-01-01
  • 用C語(yǔ)言實(shí)現(xiàn)自動(dòng)售貨機(jī)

    用C語(yǔ)言實(shí)現(xiàn)自動(dòng)售貨機(jī)

    這篇文章主要為大家詳細(xì)介紹了用C語(yǔ)言實(shí)現(xiàn)自動(dòng)售貨機(jī),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • Dijkstra算法與Prim算法的異同案例詳解

    Dijkstra算法與Prim算法的異同案例詳解

    這篇文章主要介紹了Dijkstra算法與Prim算法的異同案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-09-09
  • C++動(dòng)態(tài)數(shù)組類(lèi)的封裝實(shí)例

    C++動(dòng)態(tài)數(shù)組類(lèi)的封裝實(shí)例

    這篇文章主要介紹了C++動(dòng)態(tài)數(shù)組類(lèi)的封裝,很重要的概念,需要的朋友可以參考下
    2014-08-08
  • C++11中強(qiáng)類(lèi)型枚舉的使用

    C++11中強(qiáng)類(lèi)型枚舉的使用

    本文主要介紹了C++11中強(qiáng)類(lèi)型枚舉的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • C++遞歸刪除一個(gè)目錄實(shí)例

    C++遞歸刪除一個(gè)目錄實(shí)例

    這篇文章主要介紹了C++遞歸刪除一個(gè)目錄的實(shí)現(xiàn)方法,涉及到目錄的操作及遞歸算法的應(yīng)用,需要的朋友可以參考下
    2014-10-10
  • C++實(shí)現(xiàn)字符串刪除字符后逆序輸出

    C++實(shí)現(xiàn)字符串刪除字符后逆序輸出

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)字符串刪除字符后逆序輸出,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • C++獲取GPU顯卡信息的示例代碼

    C++獲取GPU顯卡信息的示例代碼

    這篇文章主要為大家詳細(xì)介紹了如何使用C++獲取GPU顯卡信息,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,有需要的小伙伴可以參考一下
    2024-02-02
  • c語(yǔ)言動(dòng)態(tài)內(nèi)存分配知識(shí)點(diǎn)及實(shí)例

    c語(yǔ)言動(dòng)態(tài)內(nèi)存分配知識(shí)點(diǎn)及實(shí)例

    在本篇文章里小編給大家整理的是關(guān)于c語(yǔ)言動(dòng)態(tài)內(nèi)存分配知識(shí)點(diǎn)及實(shí)例,需要的朋友們可以學(xué)習(xí)下。
    2020-03-03

最新評(píng)論