一.同名覆蓋引發的問題
父子間的賦值相容--子類物件可以當作父類物件使用(相容性)
1.子類物件可以直接賦值給父類物件
2.子類物件可以直接初始化父類物件
3.父類指標可以指向子類物件
4.父類引用可以直接引用子類物件
**示例
#include
#include
using namespace std;
class parent
public:
int mi;
void add(int i)
mi += i;
void add(int a, int b)
mi += (a + b);
class child : public parent
public:
int mv;
void add(int x, int y, int z)
mv += (x + y + z);
int main()
parent p;
child c;
p = c;
parent p1(c);
parent& rp = c;
parent* pp = &c;
rp.mi = 100;
rp.add(5);
rp.add(10, 10);
pp->mv = 1000;
pp->add(1, 10, 100);
return 0;
對該**進行結果**:通過之前的學習的同名覆蓋,程式會在 rp.add(5); rp.add(10, 10); 進行同名覆蓋,且在父類指標指向子類物件時可以進行呼叫
執行結果
通過程式的執行結果看到,與**的結果不同,這是因為當使用父類指標(引用)指向子類物件時
1.子類物件退化為父類物件--所以在pp->mv時會出錯
2.只能訪問父類中定義的成員
3.可以直接訪問被子類覆蓋的同名成員--所以沒發生同名覆蓋
特殊的同名函式
1.子類中可以重定義父類中已經存在的成員函式
2.這種重定義發生在繼承中,叫做函式重寫
3.函式重寫是同名覆蓋的一種特殊情況
q:當函式重寫遇上賦值相容會發生什麼?
**示例
#include
#include
using namespace std;
class parent
public:
int mi;
void add(int i)
mi += i;
void add(int a, int b)
mi += (a + b);
void print()
cout << "i'm parent." << endl;
class child : public parent
public:
int mv;
void add(int x, int y, int z)
mv += (x + y + z);
void print()
cout << "i'm child." << endl;
void how_to_print(parent* p)
p->print();
int main()
parent p;
child c;
how_to_print(&p);
how_to_print(&c);
return 0;
輸出結果
問題分析
1.編譯期間,編譯器只能根據指標的型別判斷所指向的物件
2.根據賦值相容,編譯器認為父類指標指向的是父類物件
3.因此,編譯結果只可能是呼叫
在編譯這個函式的時候,編譯器不可能知道指標p指向了什麼,但是編譯器沒有理由報錯。於是,編譯器認為最安全的做法時呼叫父類的print函式因為父類和子類肯定都有相同的print函式
二.多型的概念和意義
函式重寫
1.父類中被重寫的函式依然會繼承給子類
2.子類中重寫的函式將覆蓋父類中的函式
3.通過作用域分辨符(::)可以訪問父類中的函式
a.物件導向中期待的行為
1.根據實際的物件型別判斷如何呼叫重寫函式
2.父類指標指向--a.父類物件呼叫父類中定義的函式b.子類物件則呼叫子類中定義的函式
b.物件導向的多型的概念
1.根據實際的物件型別決定函式呼叫的具體目標
2.同樣的呼叫語句在實際執行時有多種不同的表現形態
c.c++語言中直接支援多型的概念
1.通過使用virtual關鍵字對多型進行支援
2.被virtual宣告的函式被重寫後具有多型特性
3.被virtual宣告的函式叫做虛函式
#include
#include
using namespace std;
class parent
public:
virtual void print()
cout << "i'm parent." << endl;
class child : public parent
public:
void print()
cout << "i'm child." << endl;
void how_to_print(parent* p)
p->print(); // 展現多型的行為
int main()
parent p;
child c;
how_to_print(&p);
how_to_print(&c);
return 0;
執行結果
d.多型的意義
1.在程式的執行過程中展現出多型的特性
2.函式重寫必須實現多型,否則沒有意義
3.多型時物件導向元件化程式設計的基礎特性
靜態聯編--在程式的編譯期間就能確定具體的函式呼叫
動態聯編--在程式實際執行後才能確定具體的函式呼叫
#include
#include
using namespace std;
class parent
public:無錫好的**醫院
virtual void func()
cout << "void func()" << endl;
virtual void func(int i)
cout << "void func(int i) : " << i << endl;
virtual void func(int i, int j)
cout << "void func(int i, int j) : " << "(" << i << ", " << j << ")" << endl;
class child : public parent
public:
void func(int i, int j)
cout << "void func(int i, int j) : " << i + j << endl;
void func(int i, int j, int k)
cout << "void func(int i, int j, int k) : " << i + j + k << endl;
void run(parent* p)
p->func(1, 2); // 展現多型的特性
// 動態聯編
int main()
parent p;
p.func();
p.func(1);
p.func(1, 2);
cout << endl;
child c;
c.func(1, 2);
cout << endl;
run(&p);
run(&c);
return 0;
執行結果
小結1.函式重寫只可能發生在父類與子類之間
2.根據實際物件的型別確定呼叫的具體函式
3.virtual關鍵字是c++中支援多型的唯一方式
4.被重寫的虛函式表現出多型的特性
C 繼承之同名覆蓋,函式重寫與多型詳解
目錄 如果父類成員和子類成員名字相同是否允許?會發生什麼?include using namespace std class base class derived public base int main int main 結果卻是都列印base class base class base clas...
C 繼承中的同名覆蓋
1,父子間的衝突是由繼承帶來的,兩個類之間存在了繼承的關係,必然的會帶來一 些問題,本文要討論的是父子之間成員變數或成員函式的命名問題 2,思考 1,子類中是否可以定義父類中的同名成員?1,可以,本文先程式設計解決這個問題 2,這個問題就是同名覆蓋問題 2,如果可以,如何區分?如果不可以,為什麼?3...
C 繼承 同名隱藏 覆蓋,虛函式
不同作用域宣告的識別符號的可見性原則 如果存在兩個或多個具有包含關係的作用域,外層宣告了乙個識別符號,而內層沒有再次宣告同名識別符號,那麼外層識別符號在內層依然可見,如果在內層宣告了同名識別符號,則外層識別符號在內層不可見,這時稱內層識別符號隱藏了外層同名識別符號,這種現象稱為隱藏規則。在類的派生層...