亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

解析C++編程中virtual聲明的虛函數以及單個繼承

2020-05-23 14:09:31
字體:
來源:轉載
供稿:網友
這篇文章主要介紹了C++編程中virtual聲明的虛函數以及單個繼承,剖析虛函數和單個基類所能夠繼承的成員,要的朋友可以參考下
 

虛函數

虛函數是應在派生類中重新定義的成員函數。 當使用指針或對基類的引用來引用派生的類對象時,可以為該對象調用虛函數并執行該函數的派生類版本。
虛函數確保為該對象調用正確的函數,這與用于進行函數調用的表達式無關。
假定基類包含聲明為 virtual 的函數,并且派生類定義了相同的函數。 為派生類的對象調用派生類中的函數,即使它是使用指針或對基類的引用來調用的。 以下示例顯示了一個基類,它提供了 PrintBalance 函數和兩個派生類的實現

// 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();  }

在前面的代碼中,對 PrintBalance 的調用是相同的,pAccount 所指向的對象除外。 由于 PrintBalance 是虛擬的,因此將調用為每個對象定義的函數版本。 派生類 PrintBalance 和 CheckingAccount 中的 SavingsAccount 函數“重寫”基類 Account 中的函數。
如果聲明的類不提供 PrintBalance 函數的重寫實現,則使用基類 Account 中的默認實現。
派生類中的函數僅在基類中的虛函數的類型相同時重寫這些虛函數。 派生類中的函數不能只是與其返回類型中的基類的虛函數不同;參數列表也必須不同。
當使用指針或引用調用函數時,以下規則將適用:
根據為其調用的對象的基本類型來解析對虛函數的調用。
根據指針或引用的類型來解析對非虛函數的調用。
以下示例說明在通過指針調用時虛函數和非虛函數的行為:

// 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::NameOfInvoked by BaseDerived::NameOfInvoked by Derived

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

CheckingAccount *pChecking = new CheckingAccount( 100.00 );pChecking->Account::PrintBalance(); // Explicit qualification.Account *pAccount = pChecking; // Call Account::PrintBalancepAccount->Account::PrintBalance();  // Explicit qualification.

在前面的示例中,對 PrintBalance 的調用將禁用虛函數調用機制。


單個繼承
在“單繼承”(繼承的常見形式)中,類僅具有一個基類。考慮下圖中闡釋的關系。

解析C++編程中virtual聲明的虛函數以及單個繼承

簡單單繼承關系圖
注意該圖中從常規到特定的進度。在大多數類層次結構的設計中發現的另一個常見特性是,派生類與基類具有“某種”關系。在該圖中,Book 是一種 PrintedDocument,而 PaperbackBook 是一種 book。
該圖中的另一個要注意的是:Book 既是派生類(來自 PrintedDocument),又是基類(PaperbackBook 派生自 Book)。此類類層次結構的框架聲明如下面的示例所示:

// deriv_SingleInheritance.cpp// compile with: /LDclass PrintedDocument {};// Book is derived from PrintedDocument.class Book : public PrintedDocument {};// PaperbackBook is derived from Book.class PaperbackBook : public Book {};

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

解析C++編程中virtual聲明的虛函數以及單個繼承

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

// 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;};

請注意,Book 的構造函數 (Book::Book) 具有對數據成員 Name 的訪問權。在程序中,可以創建和使用類型為 Book 的對象,如下所示:

// 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();

如前面的示例所示,以相同的方式使用類成員和繼承的數據和函數。如果類 Book 的實現調用 PrintNameOf 函數的重新實現,則只能通過使用范圍解析 (Document) 運算符來調用屬于 :: 類的函數:

// 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();}

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

// deriv_SingleInheritance4.cpp// compile with: /W3struct 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;}

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



發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美大人香蕉在线| 日韩在线观看免费高清完整版| 久久久久久亚洲精品| 国产第一区电影| 欧美疯狂性受xxxxx另类| 日韩中文字幕视频在线观看| 欧美极品欧美精品欧美视频| 国产精品高潮呻吟久久av黑人| 亚洲精品电影网站| 亚洲人a成www在线影院| 亚洲精品www久久久久久广东| 久久久噜久噜久久综合| 91国偷自产一区二区三区的观看方式| www.欧美三级电影.com| 亚洲国产美女久久久久| 亚洲小视频在线观看| 97免费视频在线| 国产精品吹潮在线观看| 精品国产一区二区三区久久久| 国产精品久久久久91| 久久久久久久一区二区三区| 日本精品视频在线| 欧美成人高清视频| 久久久精品免费视频| 亚洲免费伊人电影在线观看av| 亚洲精品美女久久| 亚洲国产精品va在线看黑人| 91成品人片a无限观看| 欧美国产日韩视频| 亚洲香蕉成人av网站在线观看| 69久久夜色精品国产7777| 日本一区二区不卡| 亚洲高清色综合| 欧美视频中文在线看| 日本电影亚洲天堂| 国模私拍视频一区| 久久天天躁狠狠躁夜夜躁| 国产精品www网站| 久久久久久久久久婷婷| 久久天天躁狠狠躁夜夜av| 91久久在线视频| 久久人人爽亚洲精品天堂| 欧美国产中文字幕| 日韩在线观看免费全| 久久久女女女女999久久| 欧美一级免费看| 久热精品在线视频| 91精品视频在线免费观看| 国产一区二区三区三区在线观看| 日韩大片在线观看视频| 久久精品国产欧美激情| 国产精品老牛影院在线观看| 国产日韩欧美自拍| 欧美日韩国产影院| 久久这里只有精品99| 久久99久久久久久久噜噜| 国产一区二区三区在线| 国产精品久久久久久影视| 亚洲石原莉奈一区二区在线观看| 81精品国产乱码久久久久久| 亚洲一区二区三区成人在线视频精品| 欧美高跟鞋交xxxxxhd| 中文字幕日韩av电影| 中文字幕久久久| 久久av红桃一区二区小说| 国产色视频一区| 欧美日韩在线看| 国产精品扒开腿爽爽爽视频| 国模精品视频一区二区三区| 日韩美女在线播放| 国内久久久精品| 精品偷拍一区二区三区在线看| 在线观看日韩av| 97视频在线观看视频免费视频| 亚洲色图50p| 日韩av在线不卡| 久久久久久网址| 欧美成人激情图片网| 日韩有码在线视频| 国产精品6699| 欧美精品aaa| 福利微拍一区二区| 米奇精品一区二区三区在线观看| 懂色av中文一区二区三区天美| 97在线看福利| 亚洲图片制服诱惑| 亚洲va男人天堂| 日韩免费在线播放| 欧美激情视频一区二区| 不卡av日日日| 影音先锋欧美精品| 国产欧美 在线欧美| 久久久女人电视剧免费播放下载| 91欧美精品午夜性色福利在线| 国产精品视频不卡| 91在线色戒在线| 久久欧美在线电影| 97国产在线视频| 国精产品一区一区三区有限在线| 欧美夫妻性生活xx| 538国产精品一区二区免费视频| 日韩精品免费在线观看| 亚洲精品成人久久久| 久久精品青青大伊人av| 国产精品劲爆视频| 一区二区三区国产在线观看| 992tv成人免费影院| 国产91成人在在线播放| 国产午夜精品理论片a级探花| 亚洲天堂一区二区三区| 国产999在线观看| 亚洲男人的天堂在线| 国产精品第100页| 日韩中文在线观看| 日韩av电影在线播放| 日韩av综合网站| 欧美日韩在线视频观看| 日韩av手机在线看| 日韩美女主播视频| 91在线直播亚洲| 黄色一区二区在线观看| 午夜欧美大片免费观看| 亚洲精品在线观看www| 久久亚洲欧美日韩精品专区| 日韩av电影在线播放| 亚洲欧美在线一区二区| 日本一区二区三区四区视频| 国产精品视频中文字幕91| 深夜精品寂寞黄网站在线观看| 国产精品成人播放| 日韩视频免费中文字幕| 久久免费福利视频| 综合欧美国产视频二区| 欧美性69xxxx肥| 国产亚洲成精品久久| 日韩成人在线观看| 亚洲欧美激情另类校园| 成人中文字幕+乱码+中文字幕| 久久久爽爽爽美女图片| 欧美日韩性视频| 日韩女优人人人人射在线视频| 91亚洲人电影| 国产精品自产拍高潮在线观看| 欧美中文字幕视频| 免费不卡在线观看av| 国产一区二区三区中文| 中文字幕久热精品视频在线| 国产精品久久久久久久久借妻| 免费不卡欧美自拍视频| 欧美国产日韩一区二区三区| 欧美日韩综合视频网址| 亚洲午夜激情免费视频| 九九九久久国产免费| 国产中文字幕亚洲| 欧美激情精品久久久久久| 亚洲天堂成人在线视频| 91国产高清在线| 久久久精品2019中文字幕神马| 精品亚洲夜色av98在线观看| 欧美日韩亚洲网| 日韩成人在线电影网| 亚洲精品久久久久久久久久久久| 欧美精品videofree1080p| 国产精品福利在线|