【C++】 48_同名覆蓋引起的問題

父子間的賦值問題

  • 子類對象能夠看成父類對象使用(兼容性)ios

    • 子類對象能夠直接賦值給父類對象
    • 子類對象能夠直接初始化父類對象
    • 父類指針能夠直接指向子類對象
    • 父類引用能夠直接引用子類對象

編程實驗: 子類對象的兼容性

#include <iostream>

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;        // Error
    // pp->add(1, 10, 100);  // Error

    return 0;
}
編譯輸出:
無錯誤,無警告

分析 1:
rp.add(5);  rp.add(10, 10); 
子類對象與父類對象中都定義了 add 函數,使用父類類型引用調用父類同名成員函數,爲何沒有發生同名覆蓋呢?

分析 2:
pp->mv = 1000; pp->add(1, 10, 100); 
子類對象中定義了成員變量 int mv; 與 void add(int x, int y, int z); 使用父類指針指向子類對象,進行調用爲何編譯器報錯呢?

test.cpp: In function ‘int main()’:
test.cpp:48: error: ‘class Parent’ has no member named ‘mv’
test.cpp:49: error: no matching function for call to ‘Parent::add(int, int,     int)’
test.cpp:10: note: candidates are: void Parent::add(int)
test.cpp:15: note:                 void Parent::add(int, int)
  • 當使用父類指針( 引用 ) 指向子類對象時編程

    • 子類對象退化爲父類對象
    • 只能訪問父類中定義的成員
    • 能夠直接訪問被子類覆蓋的同名成員

特殊的同名函數

  • 子類中能夠重定義父類中已經存在的成員函數
  • 這種重定義發生在繼承中,叫作函數重寫【子類與父類成員函數的函數類型相同】
  • 函數重寫是同名覆蓋的一種特殊狀況
class Parent
{
public:
    void print()
    {
        cout << "I'm Parent." << endl;
    }
};

函數重寫 ==>安全

class Child : public Parent
{
public:
    void print()
    {
        cout << "I'm Child" << endl;
    }
};

思考

當函數重寫趕上賦值兼容會發生什麼?函數

編程實驗: 賦值兼容的問題

#include <iostream>

using namespace std;

class Parent
{
public:
    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);    // Expected to print: I'm Parent 
    how_to_print(&c);    // Expected to print: I'm Child 
    
    return 0;
}
輸出:
I'm Parent.
I'm Parent.

現象:
how_to_print(&c); 爲何不是指望的輸出呢?這讓咱們在使用時產生困惑,甚至產生軟件錯誤!
  • 問題分析spa

    • 編譯期間,編譯器只能根據指針的類型判斷所指向的對象
    • 根據賦值兼用, 編譯器認爲父類指針指向的是父類對象
    • 所以,編譯結果只多是調用父類中的同名函數

void how_to_print(Parent* p)
{
    p->print();
}

在編譯這個函數的時候,編譯器不可能知道指針 p 究竟指向了什麼。可是編譯器沒有理由報錯(語法正確)。因而,編譯器認爲最安全的作法是調用父類的 print 函數, 由於父類和子類確定都有相同的 print 函數。指針

問題

編譯器的處理方法是合理的嗎? 是指望的嗎?code

合理,非指望!對象

(將在下一課中說明解決方法...)繼承

小結

  • 子類對象能夠看成父類對象使用(賦值兼容)
  • 父類指針能夠正確的指向子類對象
  • 父類引用能夠正確的表明子類對象
  • 子類中能夠重寫父類中的成員函數

以上內容參考狄泰軟件學院系列課程,請你們保護原創!編譯器

相關文章
相關標籤/搜索