c++面向對象高級編程 學習十六 vptr和vtbl

當一個類中有一個或多個虛函數時,內存中會多一個虛指針(vptr,virtual pointer),指向一個虛表(vtbl,virtual table)

父類有虛函數,則子類一定有虛函數

在下圖示意圖中,我們可知,B繼承A,C繼承B。
A有兩個虛函數,B繼承A則也有兩個虛函數,同時B對虛函數vfunc1進行了重寫,同理,C繼承B,則C也有兩個虛函數,C對虛函數vfunc1也進行了重寫。故在內存中,A B C對應的虛函數vfunc2是同一個均為A::vfunc2,對應的虛函數vfunc1分別為A::vfunc1,B::vfunc1,C::vfunc1。

在這里插入圖片描述
c++編譯器遇到函數調用時,會有兩個考量,是靜態綁定還是動態綁定,靜態綁定是call xxx地址,即一定調用到某個地址,動態綁定可以調用到不同的地址

動態綁定需符合三個條件:

  • 通過指針調用(對象調用函數是靜態綁定
  • 指針是向上的關系,向上關系是指,比如 父類 名稱 = new 子類(),這樣的關系即是一種向上的關系
  • 調用的是虛函數

虛函數的這種用法,稱之為多態

示例程序:

#include<iostream>
using namespace std;class A {
public:A(int data1, int data2) :m_data1(data1), m_data2(data2) {}virtual void vfunc1() { cout << "調用的是A的vfunc1"<< endl; }virtual void vfunc2() { cout << "調用的是A的vfunc2" << endl; }void func1() { cout << "調用的是A的func1" << endl; }void func2() { cout << "調用的是A的func2" << endl; }void getData() {cout << "A的m_data1:" << m_data1 << ",A的m_data2:" << m_data2 << endl;}
private:int m_data1, m_data2;
};class B:public A {
public:B(int n1,int n2,int n3) :A(n1,n2), m_data3(n3){}virtual void vfunc1() { cout << "調用的是B的vfunc1" << endl; }void func2() { cout << "調用的是B的func2" << endl; }void getData() {A::getData();cout << "B的m_data3:" << m_data3  << endl;}
private:int m_data3;
};class C :public B {
public:C(int n1, int n2, int n3,int n4,int n5):B(n1,n2,n3) , m_data1(n4), m_data4(n5) {}virtual void vfunc1() { cout << "調用的是C的vfunc1" << endl; }void func2() { cout << "調用的是C的func2" << endl; }void getData() {B::getData();cout << "C的m_data1:" << m_data1 << ",C的m_data4:" << m_data4 << endl;}
private:int m_data1, m_data4;
};

測試程序:

int main()
{A a(1,2);a.vfunc1();a.vfunc2();a.func1();a.func2();a.getData();cout << endl;B b(3,4,5);b.vfunc1();b.vfunc2();b.func1();b.func2();b.getData();cout << endl;C c(6,7,8,9,10);c.vfunc1();c.vfunc2();c.func1();c.func2();c.getData();cout << endl;A* d = new B(1,3,5);d->vfunc1();d->vfunc2();d->func1();d->func2();d->getData();cout << endl;A* d2 = new C(1, 3, 5,7,9);d2->vfunc1();d2->vfunc2();d2->func1();d2->func2();d2->getData();system("pause");return 0;
}

輸出結果:

調用的是A的vfunc1
調用的是A的vfunc2
調用的是A的func1
調用的是A的func2
A的m_data1:1,A的m_data2:2調用的是B的vfunc1
調用的是A的vfunc2
調用的是A的func1
調用的是B的func2
A的m_data1:3,A的m_data2:4
B的m_data3:5調用的是C的vfunc1
調用的是A的vfunc2
調用的是A的func1
調用的是C的func2
A的m_data1:6,A的m_data2:7
B的m_data3:8
C的m_data1:9,C的m_data4:10調用的是B的vfunc1
調用的是A的vfunc2
調用的是A的func1
調用的是A的func2
A的m_data1:1,A的m_data2:3調用的是C的vfunc1
調用的是A的vfunc2
調用的是A的func1
調用的是A的func2
A的m_data1:1,A的m_data2:3

從輸出結果中,我們可以看出,當對函數進行重寫后,子類在調用函數時會調用重寫后的函數。當函數是虛函數時,若我們按照父類 名稱 = new 子類() 的形式生成指針,則該指針在調用函數時,若調用的函數是虛函數,則其會調用子類重寫后的虛函數,若調用的函數不是虛函數,則無論子類對該函數是否重寫,調用的均為父類的函數。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/446586.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/446586.shtml
英文地址,請注明出處:http://en.pswp.cn/news/446586.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

英語口語Week16 Thursday

英語文章 It is an impossibility that everything runs smoothly in everyday life. Where there is trouble, there could be anxiety.Anxiety is a common phenomenon; you are not the only one carrying it. But, it could be somewhat poisonous if you don’t let it o…

c++面向對象高級編程 學習十七 const, new, delete

文章目錄常量成員函數new和delete常量成員函數 常量成員函數是不改變成員數據。 當成員函數的const和non-const版本同時存在時&#xff0c;const object只能調用const版本&#xff0c;non-const object只能調用non-const版本。因此&#xff0c;可以看出&#xff0c;const是函…

codeforces 467A-C語言解題報告

題目網址 題目解析 1.輸入n個房間,再每一行輸入現有的p個人,和一共可以容納的q人數,如果q-p>2則計數1 代碼 #include<stdio.h> #include<stdlib.h> #include<string.h>int main() {int n0,p0,q0;int count0,i;scanf("%d",&n);for(i0;i&…

使用引用的方式交換數據的數值

#include <iostream>void swap(int &a,int &b){a ^ b;b ^ a;a ^ b; } int main(){int num1 10;int num2 20;swap(num1,num2);std::cout << num1 << std::endl;std::cout << num2 << std::endl; }

C++STL與泛型編程 侯捷 (1)

泛型編程&#xff08;Generic Programming&#xff0c;GP&#xff09;&#xff0c;就是使用template&#xff08;模板&#xff09;為主要工具來編寫程序。 重要網頁&#xff1a; http://www.cplusplus.com/ https://en.cppreference.com/w/ http://gcc.gnu.org/

codeforces 136A-C語言解題報告

題目網址 題目解析 1.輸入每個人給第幾個人發禮物(1–n), 輸出每個人收到第幾個人發的禮物 2.因為1–n,所以for循環也使用1–n output[input[j]]j; 代碼 #include<stdio.h> #include<stdlib.h> #include<string.h> int main() {int n0;scanf("%d&…

static內容相關介紹學習

說一下static關鍵字的作用 當程序執行到函數內部定義的變量時&#xff0c;編譯器為它在棧上分配空間&#xff0c;函數在棧上分配的空間在此函數執行結束時會釋放掉&#xff0c;這樣就產生了一個問題: 如果想將函數中此變量的值保存至下一次調用時&#xff0c;如何實現&#xf…

C++STL與泛型編程(2) 第一個C++ STL Application

文章目錄STL六大部件STL六大部件代碼示例時間復雜度前閉后開區間auto關鍵字的用法STL六大部件 容器 分配器 算法 迭代器 適配器 仿函數 容器要放東西&#xff0c;東西要占用內存&#xff0c;分配器可支持容器解決內存問題。算法處理容器中的數據。迭代器是容器和算法之間的橋…

codeforces 344A-C語言解題報告

題目網址 題目解析 1.有10和01兩種,同性相斥,異性相吸 2.01是1,使用pre去記錄前一個,寫出所有情況 0110 1001 分為一組 代碼 #include<stdio.h> #include<stdlib.h> #include<string.h> int main() {int n0;int i0;int c0;int pre-1;int count0;scanf(&…

JAVA 程序執行進行計時,用于驗證程序執行的時間

package com.example.algorithm.demo.class1;public class Hello {public static void main(String[] args) {long start System.nanoTime();//程序開始時間System.out.println(start);System.out.println("Hello");long end System.nanoTime();System.out.println…

C++STL與泛型編程__侯捷視頻_學習博客_總目錄

CSTL與泛型編程 侯捷 &#xff08;1&#xff09;: c重要網站相關 CSTL與泛型編程&#xff08;2&#xff09; 第一個C STL Application&#xff1a; STL六大部件代碼示例&#xff0c;容器前閉后開區間&#xff0c;auto關鍵字的用法示例 CSTL與泛型編程&#xff08;3&#xff0…

codeforces 1030A-C語言解題報告

題目網址 題目解析 1.輸入一串數字,如果有1就輸出HARD,否則輸出EASY 2.勿忘& 代碼 #include<stdio.h> #include<stdlib.h> #include<string.h> int main() {int n0,i0;int num0;int count0;scanf("%d",&n);for(i;i<n;i){scanf(&quo…

C++STL與泛型編程(3)容器之分類與測試

文章目錄容器的分類序列式容器&#xff08;sequence containers&#xff09;代碼示例輔助函數array 容器array容器的測試代碼測試代碼中部分函數解析vector 容器vector 容器的測試代碼測試代碼中部分函數解析list 容器list 容器的測試代碼測試代碼中部分函數解析forward_list 容…

codeforces 318A-C語言解題報告

題目網址 題目 1.一個數先奇數從小到大再偶數從小到大(1–n),問第k個數是什么? 2.舉例發現規律: 第k個數與n的奇偶無關,使用中間數mid(a1)/2;進行判斷,k是奇數還是偶數 奇數:countb*2-1; 偶數:count(b-mid)*2; 3.因為數很大,使用scanf("%lld %lld",&a,&…

C++面試題目

C和C的區別 總覽 C是一個結構化語言&#xff0c;它的重點在于算法和數據結構。C程序的設計首要考慮的是如何通過一個過程&#xff0c;對輸入&#xff08;或環境條件&#xff09;進行運算處理得到輸出&#xff08;或實現過程&#xff08;事務&#xff09;控制&#xff09;。C&…

C++STL與泛型編程(4)OOP(面向對象編程) Vs. GP(泛型編程)

文章目錄OOP和GP為什么list不能使用標準庫中的::sort算法&#xff1f;采用GP的好處OOP和GP OOP將datas和methods關聯在一起 GP將datas和methods分開 為什么list不能使用標準庫中的::sort算法&#xff1f; 因為標準庫的sort的算法用到了隨機訪問迭代器&#xff08;RandomAcce…

codeforces 158B-C語言解題報告

題目網址 題目解析 參考博客 代碼 #include<iostream> #include<string.h> #include<algorithm> #include<stdio.h> #include<math.h> using namespace std; int n,a[100005]; long long sum,s1,s2,s3;main() {cin>>n;for(int i1;i<…

ECC 公鑰加密 使用相同的ECC公鑰對 對 相同的數據進行加密,每次的加密結果是一致的嗎?

ECC 公鑰加密 使用相同的ECC公鑰對 對 相同的數據進行加密&#xff0c;每次的加密結果是一致的嗎&#xff1f;不一致里面包裝了個臨時的點&#xff0c;使用這個增加安全性

C++ primer 第7章 類

成員函數的聲明必須在類的內部&#xff0c;定義則既可以在類的內部&#xff0c;也可以在類的外部。 作為接口組成部分的非成員函數&#xff0c;它們的定義和聲明都在類的外部。 類可以允許其他類或者函數訪問它的非公有成員&#xff0c;方法是令其他類或函數成為它的友元。如果…

codeforces 705A-C語言解題報告

題目網址 題目解析 1.重點:結尾是it,中間使用that連接,所以使用for循環,奇數輸出I hate,偶數輸出I love,i!n時,輸出that 代碼 #include<stdio.h> #include<stdlib.h> #define SIZE 100000 int main() {int n0;scanf("%d",&n);if(n1){printf(&quo…