C 之同名覆蓋 多型

2022-06-10 07:06:10 字數 4064 閱讀 7214

一.同名覆蓋引發的問題

父子間的賦值相容--子類物件可以當作父類物件使用(相容性)

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 繼承 同名隱藏 覆蓋,虛函式

不同作用域宣告的識別符號的可見性原則 如果存在兩個或多個具有包含關係的作用域,外層宣告了乙個識別符號,而內層沒有再次宣告同名識別符號,那麼外層識別符號在內層依然可見,如果在內層宣告了同名識別符號,則外層識別符號在內層不可見,這時稱內層識別符號隱藏了外層同名識別符號,這種現象稱為隱藏規則。在類的派生層...