C++中基類和派生類之間的轉(zhuǎn)換實(shí)例教程
本文實(shí)例講解了C++中基類和派生類之間的轉(zhuǎn)換。對(duì)于深入理解C++面向?qū)ο蟪绦蛟O(shè)計(jì)有一定的幫助作用。此處需要注意:本文實(shí)例講解內(nèi)容的前提是派生類繼承基類的方式是公有繼承,關(guān)鍵字public。具體分析如下:
以下程序?yàn)橹v解示例:
#include<iostream>
using namespace std;
class A
{
public:
A(int m1, int n1):m(m1), n(n1){}
void display();
private:
int m;
int n;
};
void A::display()
{
cout << "m = " << m << endl;
cout << "n = " << n << endl;
}
class B :public A
{
public:
B(int m1, int n1, int p1) :A(m1, n1), p(p1){}
void display();
private:
int p;
};
void B::display()
{
A::display();
cout << "p = " << p << endl;
}
void print1(A& a)
{
a.display();
}
void print2(B& b)
{
b.display();
}
void print3(A a)
{
a.display();
}
void print4(B b)
{
b.display();
}
int main()
{
A a(3, 4);
// a.display();
B b(10, 20, 30);
// b.display();
A * pa;
B * pb;
pa = &a;
// pa->display();
pb = &b;
// pb->display();
// pa = &b;
// pa->display();
// pb = &a; //錯(cuò)誤。派生類指針不能指向基類對(duì)象。
// print1(b);
// print2(a); //錯(cuò)誤。不能用基類對(duì)象給派生類引用賦值。
// print3(b);
// print4(a); //錯(cuò)誤。不能用基類對(duì)象給派生類對(duì)象賦值。
// pb = pa; //不能用基類指針給派生類指針賦值。
pb = (B*)pa; //可以強(qiáng)制轉(zhuǎn)換,但是非常不安全。
pb->display(); //出現(xiàn)安全問(wèn)題,p無(wú)法訪問(wèn),因?yàn)閍中沒(méi)有p成員
system("pause");
return 0;
}
切記:派生類對(duì)象是基類對(duì)象,派生類中包含有基類的成員?;悓?duì)象不是派生類對(duì)象,它不能包含派生類型的成員。
一、派生類到基類的轉(zhuǎn)化
1.派生類對(duì)象地址賦值給基類指針
main函數(shù)中執(zhí)行以下代碼
A a(3, 4); // a.display(); B b(10, 20, 30); // b.display(); A * pa; // B * pb; // pa = &a; // pa->display(); // pb = &b; // pb->display(); pa = &b; pa->display(); //會(huì)輸出 10 20
pa為基類指針,指向派生類對(duì)象是合法的,因?yàn)榕缮悓?duì)象也是基類對(duì)象。語(yǔ)句會(huì)輸出派生類對(duì)象中基類部分。
注意:這里并不會(huì)調(diào)用派生類的display函數(shù),調(diào)用的是基類的display函數(shù),因?yàn)橹羔榩a是基類指針,編譯器在編譯階段只知道pa的類型。如果要實(shí)現(xiàn)調(diào)用派生類的display函數(shù),需要用到虛函數(shù)實(shí)現(xiàn)多態(tài)性。之后的文章會(huì)講到。
進(jìn)一步解釋一下編譯時(shí)和運(yùn)行時(shí)的區(qū)別。
編譯時(shí)編譯器能知道pa的類型為A *,但是不知道它指向了哪個(gè)對(duì)象,假如有以下語(yǔ)句
A a(3, 4); B b(10, 20, 30); A* pa; int number; cin >> number; if (number >= 0) pa = &a; else pa = &b;
pa指向的對(duì)象類型依賴于輸入,運(yùn)行時(shí)才輸入,所以編譯器是沒(méi)有辦法知道pa指向哪個(gè)類型的。
2.派生類對(duì)象賦值給基類引用
引用跟指針基本沒(méi)有區(qū)別,引用本質(zhì)上是指針,是個(gè)指針常量,具體可以參照我的另一篇C++中的引用和指針的聯(lián)系和區(qū)別
main函數(shù)中執(zhí)行以下代碼
A a(3, 4); B b(10, 20, 30); print1(b); //會(huì)輸出 10 20
形參為基類引用,實(shí)參為派生類對(duì)象,派生類對(duì)象也是基類對(duì)象,可以賦值給基類引用。輸出派生類中基類部分。
注意:此時(shí)對(duì)象本身并未復(fù)制,b仍然是派生類對(duì)象,前面說(shuō)過(guò)了引用就是一個(gè)指針。
3.派生類對(duì)象賦值給基類對(duì)象。
A a(3, 4); B b(10, 20, 30); print3(b);
派生類對(duì)象基類部分被復(fù)制給形參。
注意:實(shí)際上沒(méi)有從派生類對(duì)象到基類對(duì)象的直接轉(zhuǎn)換。對(duì)基類對(duì)象的賦值或初始化,實(shí)際上在調(diào)用函數(shù),初始化時(shí)調(diào)用構(gòu)造函數(shù),賦值時(shí)調(diào)用賦值操作符。
二、基類到派生類的轉(zhuǎn)化
切記:這種轉(zhuǎn)換有可能引發(fā)嚴(yán)重的安全問(wèn)題,編寫代碼時(shí)不要使用。沒(méi)有基類到派生類的自動(dòng)轉(zhuǎn)換,原因在于基類對(duì)象只能是基類對(duì)象,不能包含派生類型的成員。
如果允許用基類對(duì)象給派生類對(duì)象賦值,那么就可以試圖使用該派生類對(duì)象訪問(wèn)不存在的成員。
A a(3, 4); B b(10, 20, 30); A * pa; B * pb; // print2(a); //錯(cuò)誤。不能用基類對(duì)象給派生類引用賦值。 // print4(a); //錯(cuò)誤。不能用基類對(duì)象給派生類對(duì)象賦值。 // pb = &a; //錯(cuò)誤。派生類指針不能指向基類對(duì)象。 pa = &a; pb = &b; //pb = pa; //錯(cuò)誤。不能用基類指針給派生類指針賦值。 pb = (B*)pa; //可以強(qiáng)制轉(zhuǎn)換,但是非常不安全。 pb->display(); //出現(xiàn)安全問(wèn)題,p無(wú)法訪問(wèn),因?yàn)閍中沒(méi)有p成員
注意到我們使用強(qiáng)制轉(zhuǎn)換時(shí),當(dāng)派生類添加了基類中不存在的成員時(shí),會(huì)出現(xiàn)安全問(wèn)題。
pb->display();會(huì)調(diào)用派生類的display函數(shù),但是它指向的內(nèi)存是基類對(duì)象a的內(nèi)存,p不存在。會(huì)出現(xiàn)嚴(yán)重后果。
相關(guān)文章
C++實(shí)現(xiàn)LeetCode(2.兩個(gè)數(shù)字相加)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(兩個(gè)數(shù)字相加),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07
Qt使用QPainter實(shí)現(xiàn)自定義圓形進(jìn)度條
這篇文章主要介紹了Qt如何使用QPainter實(shí)現(xiàn)自定義圓形進(jìn)度條功能,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Qt有一定的幫助,需要的可以參考一下2022-06-06
C++實(shí)現(xiàn)廣度優(yōu)先搜索實(shí)例
這篇文章主要介紹了C++實(shí)現(xiàn)廣度優(yōu)先搜索,對(duì)于C++程序員來(lái)說(shuō)非常有借鑒價(jià)值,需要的朋友可以參考下2014-08-08

