1. 程式人生 > >C++子類物件隱藏了父類的同名成員函式(隱藏篇)

C++子類物件隱藏了父類的同名成員函式(隱藏篇)

#include <iostream>
#include <stdlib.h>
#include <string>
using namespace std;


/**
 * 定義人類: Person
 * 資料成員: m_strName
 * 成員函式: attack()
 */
class Person
{
public:
    Person()
    {
        cout<<"Person()"<<endl;
    }
    Person(const Person& p)
    {
        cout<<"Person(const Person& p)"<<endl;

    }
    string m_strName;
void attack()
{
cout << "attack" << endl;
}
};


/**
 * 定義士兵類: Soldier
 * 士兵類公有繼承人類
 * 資料成員: m_strName
 * 成員函式: attack()
 */
class Soldier:public Person
{
public:
    Soldier()
    {
        cout<<"Soldier()"<<endl;
    }
string m_strName;
void attack()
{
cout << "fire!!!" << endl;

}
};


int main(void)
{
    // 例項士兵物件
   Soldier soldier;//例項化子類,會先呼叫基類建構函式,再呼叫子類的建構函式,析構時,則相反,先析構子類的,再析構基類的
    Person p = soldier;//可以看出子類的物件可以初始化基類的物件,並且這種方式會呼叫基類的拷貝建構函式

    // 向士兵屬性賦值"tomato"
    soldier.m_strName = "tomato";
    // 通過士兵物件向人類屬性賦值"Jim"
soldier.Person::m_strName = "Jim";
    // 列印士兵物件的屬性值
cout << soldier.m_strName << endl;

    // 通過士兵物件列印人類屬性值
cout << soldier.Person::m_strName << endl;//注意這種使用子類的物件呼叫基類成員變數的方式
    // 呼叫士兵物件方法
soldier.attack();
    // 通過士兵物件呼叫人類方法
    soldier.Person::attack();//注意這種使用子類的物件呼叫基類的成員函式的方式


return 0;

}

輸出結果:

Person()
Soldier()
Person(const Person& p)
tomato
Jim
fire!!!
attack
通過上面的例子,對於基類和子類之間的特性可以做如下的總結:
(1)當子類中含有和基類同名的成員變數時,再用子類的物件呼叫該同名成員變數時,將只會呼叫到子類自身定義的成員變數,而不會呼叫到基類的同名成員變數,這種現象就叫做隱藏,子類把基類的同名成員變數隱藏了,正確呼叫方式如上面例子中橘色字型部分:soldier.Person::m_strName
(2)當子類中含有和基類同名的成員函式時,再用子類的物件呼叫該同名成員函式時,將只會呼叫到子類自身定義的成員函式,而不會呼叫到基類定義的同名的成員函式,這也是因為子類把基類的同名成員函式隱藏了;正確呼叫方法應該是如上面例子中橘色字型部分:soldier.Person::attack();
這裡要強調的是何為同名成員函式,即不管引數是否相同、返回值是否相同,只要函式名稱相同,就是同名成員函式,如果子類和基類定義了這樣的函式,子類就會把基類的相應函式隱藏掉。在上面的例子中加入我們在基類Person的attack()函式裡面新增引數int x,這個時候用soldier.attack(5)這種方式試圖呼叫基類的attack()仍然會報錯,是呼叫不到的。