C++關(guān)于指針,繼承和多態(tài)介紹
指針
我們在書本上學(xué)到的指針基本上都是:首先,指針是一個變量;其次,這個變量存儲的值是一個地址。這個是對指針的一個基本理解,最近在編程中發(fā)現(xiàn)了一些新的東西。
首先,指針不僅僅是一個地址,還存在一個和所指向內(nèi)容大小相關(guān)的值,如下代碼:
#include<iostream>
using namespace std;
int main()
{
int a = 10;
int *pa = &a;
cout << "pa: " << pa << endl;
cout << "pa+1: " << pa + 1 << endl;
short b = 1;
short *pb = &b;
cout << "pb: " << pb << endl;
cout << "pb+1: " << pb + 1 << endl;
void *ppa = &a;
cout << "ppa:" << ppa << endl;
cout << "ppa+1: " << ppa + 1 << endl;
return 0;
}

從運行結(jié)果可以看出pa+1,地址增加了4個字節(jié);pb+1,地址增加了2個字節(jié);ppa+1,地址增加了2個字節(jié);而使用void指針指向整型變量a,此時ppa+1,地址只增加了1個自己。從這個結(jié)果我們可以很明顯看出,指針不僅僅是一個存地址的變量,還存在一個和內(nèi)存分配相關(guān)的值。其實進一步說,指針不僅僅是一個地址值,還存放著如何解釋內(nèi)存的規(guī)則。(void指針只存放地址,沒有解釋規(guī)則)
指針和繼承
眾所周知,繼承可以實現(xiàn)用父類的指針來指向子類的對象,為什么可以這樣用呢?正如上面所說,指針保存地址和解釋內(nèi)存的規(guī)則,當(dāng)你聲明一個父類指針,那么你就指明了該指針的解釋規(guī)則,當(dāng)你將子類地址傳給指針時,你就相當(dāng)于給了一塊內(nèi)存給這個指針,然后這個指針就可以用它的規(guī)則去解釋這塊內(nèi)存。根據(jù)上面的說法,那么我們可以得出,子類對象中必定存在一塊內(nèi)存,其分配方式和父類對象一模一樣(如果把這塊內(nèi)存單獨提取出來,它就是一個父類對象),事實也是如此,而且這塊“父類對象”一般都是存放在子類對象的最前面,這就解釋了子類在構(gòu)造的時候,一定會先調(diào)用父類構(gòu)造函數(shù)。同時,“父類對象”指針只能訪問自己的父類成員。那么考慮多繼承的情況,多繼承的子類,其內(nèi)存空間中必定存在多個“父類對象”空間,這些父類空間的地址必定是不同的,那么就會造成同一個多繼承的子類,用其不同的父類指針指向它,其地址值是不同的,實際測試的確如此:
#include<iostream>
using namespace std;
class A
{
public:
int a = 10;
long int aa = 100;
};
class B
{
public:
int b = 20;
};
class C : public A, public B
{
public:
int c = 30;
};
int main()
{
C c;
A *pA;
B *pB;
C *pC;
pA = &c;
pB = &c;
pC = &c;
cout << "pA: " << pA << endl;
cout << "pB: " << pB << endl;
cout << "pC: " << pC << endl;
cout << "pA.a: " << &(pA->a) << endl;
cout << "pA.aa: " << &(pA->aa) << endl;
cout << "pB.b: " << &(pB->b) << endl;
cout << "pC.c: " << &(pC->c) << endl;
return 0;
}


其內(nèi)存布局如圖,pA、pB都指向各自的“父類對象”空間起始位置,pA只能訪問a、aa,pB只能訪問b(至于為什么a是int卻占8個字節(jié),這個和內(nèi)存對齊有關(guān),自行查詢)。
指針、繼承和多態(tài)
C++的繼承和多態(tài)繞不過的一個東西便是虛指針和虛函數(shù),這里簡單說一下:首先,在含有虛函數(shù)的類中,會產(chǎn)生一個虛函數(shù)表,注意這個虛函數(shù)表是從屬于類的,不是從屬于對象,也就是多個對象共享這個虛函數(shù)表。其次,每個類聲明的對象都會有一個虛指針,這個虛指針指向類的虛函數(shù)表。(這里只是簡單提及一下,更多的東西可以自行查詢)看過很多網(wǎng)上的東西,都說虛指針是每個對象的第一個數(shù)據(jù)成員,也就是分配在最開頭的地址空間。其實,我覺得這句話不完全正確,因為當(dāng)多繼承中有虛函數(shù)時,虛函數(shù)表就有多個,虛指針也有多個,這些虛指針不一定全都存在于最開始的地址空間。應(yīng)該說,這些虛指針存在于繼承的父類所管理區(qū)域的開頭:
#include<iostream>
using namespace std;
class A
{
public:
int a = 10;
long int aa = 10;
virtual void f()
{
}
};
class B
{
public:
int b = 20;
virtual void g()
{
}
};
class C : public A, public B
{
public:
int c = 30;
virtual void cc()
{
}
};
int main()
{
A *pA;
B *pB;
C c;
pA = &c;
pB = &c;
cout << pA << endl;
cout << &(pA->a) << endl;
cout << &(pA->aa) << endl;
cout << pB << endl;
cout << &(pB->b) << endl;
cout << &(c.c) << endl;
return 0;
}


從上面的結(jié)果可以看出,虛指針不一定都是存在最開始的位置,如果硬要說是開始,應(yīng)該也是相對于“父類對象”區(qū)域的開始。
到此這篇關(guān)于C++關(guān)于指針,繼承和多態(tài)介紹的文章就介紹到這了,更多相關(guān)C++指針 繼承 多態(tài)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Cocos2d-x UI開發(fā)之CCControlPotentiometer控件類使用實例
這篇文章主要介紹了Cocos2d-x UI開發(fā)之CCControlPotentiometer控件類使用實例,本文代碼中包含注釋來講解CCControlPotentiometer控件類的使用,需要的朋友可以參考下2014-09-09
vscode實現(xiàn)本地代碼自動同步到遠(yuǎn)程機器的步驟
這篇文章主要介紹了vscode實現(xiàn)本地代碼自動同步到遠(yuǎn)程機器的步驟,本文分步驟給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-06-06
Windows網(wǎng)絡(luò)編程之winsock實現(xiàn)文件傳輸示例
這篇文章主要介紹了Windows網(wǎng)絡(luò)編程之winsock實現(xiàn)文件傳輸示例,對于學(xué)習(xí)Windows網(wǎng)絡(luò)程序設(shè)計來說具有很好的學(xué)習(xí)借鑒價值,需要的朋友可以參考下2014-08-08
詳解C語言中的wait()函數(shù)和waitpid()函數(shù)
這篇文章主要介紹了C語言中的wait()函數(shù)和waitpid()函數(shù),注意其在中斷進程方面用法的不同,需要的朋友可以參考下2015-08-08

