一、開宗明義
1.派生類到基類的轉化存在,這是理解多態的基礎;
2.基類到派生類的轉化不存在;
3. 派生類到基類的轉化包括以下三種情況:
- 派生類對象轉化爲基類對象
- 基類對象指針指向派生類對象
- 用派生類對象初始化積累對象的引用
二、派生類到基類的轉化
1.派生類對象轉化爲基類對象
轉化的結果就是:派生類新增的數據類型全部捨棄,而調用函數時只能調用基類的函數。這就是一個砍掉的派生類多餘部分的過程。派生類對象也是基類對象。
#include <iostream>
using namespace std;
//基類
class A {
public:
A(int a) { m_a = a; }
public:
void display();
public:
int m_a;
};
void A::display() {
cout << "基類A: m_a=" << m_a << endl;
}
//派生類
class B : public A {
public:
B(int a, int b) : A(a), m_b(b) { }
public:
void display();
public:
int m_b;
};
void B::display() {
cout << "派生類B: m_a=" << m_a << ", m_b=" << m_b << endl;
}
int main() {
A a(10);
B b(66, 99);
cout << "賦值前:" << endl;
a.display();
b.display();
cout << "--------------" << endl;
cout << "賦值前:" << endl;
a = b;
a.display();
b.display();
return 0;
}
2.基類對象指針指向派生類對象
引用跟指針基本沒有區別,引用本質上是指針,是個指針常量。所以第二種、第三種轉化可以認爲效果是一樣的。
基類對象指針只能調用基類中有的部分,不能通過基類指針訪問基類沒有而派生類中有的成員。跟第一種情況是一樣的。
#include <iostream>
using namespace std;
//基類
class A {
public:
A(int a) { m_a = a; }
public:
void display();
public:
int m_a;
};
void A::display() {
cout << "基類A: m_a=" << m_a << endl;
}
//派生類
class B : public A {
public:
B(int a, int b) : A(a), m_b(b) { }
public:
void display();
public:
int m_b;
};
void B::display() {
cout << "派生類B: m_a=" << m_a << ", m_b=" << m_b << endl;
}
int main() {
A a(10);
B b(66, 99);
cout << "賦值前:" << endl;
a.display();
b.display();
cout <<endl<< "a=b 賦值後:" << endl;
a = b;
b.m_a = 1000;
b.display();
cout <<endl<< "A*ps=&b賦值後:" << endl;
A*ps = &b;
ps->m_a = 100;
//ps->m_b = 100;錯誤,不存在m_b
b.display();
return 0;
}
可以發現,無論是派生類對象直接給基類對象賦值,或者是基類指針指向派生類。
基類操作之後派生類都會發生變化,所以轉化過程並沒有開闢一塊新的內存。
參考資料:
https://www.cnblogs.com/piginthetree/p/3891885.html
http://c.biancheng.net/view/260.html