我們定義一個動物類,對於動物來說,它應該具有吃、睡覺和呼吸的方法。
class animal
{
public:
void eat()
{
cout<<"animal eat"<<endl;
}
void sleep()
{
cout<<"animal sleep"<<endl;
}
void breathe()
{
cout<<"animal breathe"<<endl;
}
};
我們再定義一個魚類,對於魚來說,它也應該具有吃、睡覺和呼吸的方法。
class fish
{
public:
void eat()
{
cout<<"fish eat"<<endl;
}
void sleep()
{
cout<<"fish sleep"<<endl;
}
void breathe()
{
cout<<"fish breathe"<<endl;
}
};
如果我們再定義一個綿羊類,對於綿羊來說,它也具有吃、睡覺和呼吸的方法,我們是否又重寫一遍代碼呢?既然魚和綿羊都是動物,是否可以讓魚和綿羊繼承動物的方法呢?在C++中,提供了一種重要的機制,就是繼承。類是可以繼承的,我們可以基於animal這個類來創建fish類,animal稱為基類(Base Class,也稱為父類),fish稱為派生類(Derived Class,也稱為子類)。派生類除了自己的成員變量和成員方法外,還可以繼承基類的成員變量和成員方法。
重寫animal和fish類,讓fish從animal繼承,代碼如例2-11所示(EX05.CPP)。
例2-11
#include <iOStream.h>
class animal
{
public:
void eat()
{
cout<<"animal eat"<<endl;
}
void sleep()
{
cout<<"animal sleep"<<endl;
}
void breathe()
{
cout<<"animal breathe"<<endl;
}
};
class fish:public animal
{
};
void main()
{
animal an;
fish fh;
an.eat();
fh.eat();
}
雖然fish類沒有顯式地編寫一個方法,但fish從animal已經繼承eat、sleep、breathe方法,我們通過編譯運行可以看到結果。
下面,我們在animal類和fish類中分別添加構造函數和析構函數,然後在main函數中定義一個fish類的對象fh,看看在構造fish類的對象時,animal類的構造函數是否被調用;如果調用,animal類和fish類的構造函數的調用順序是怎樣的。完整代碼如例2-12所示(EX06.CPP)。
例2-12
#include <iOStream.h>
class animal
{
public:
animal()
{
cout<<"animal construct"<<endl;
}
~animal()
{
cout<<"animal destruct"<<endl;
}
void eat()
{
cout<<"animal eat"<<endl;
}
void sleep()
{
cout<<"animal sleep"<<endl;
}
void breathe()
{
cout<<"animal breathe"<<endl;
}
};
class fish:public animal
{
public:
fish()
{
cout<<"fish construct"<<endl;
}
~fish()
{
cout<<"fish destruct"<<endl;
}
};
void main()
{
fish fh;
}
編譯運行,出現如圖2.11所示的結果。
可以看到當構造fish類的對象fh時,animal類的構造函數也要被調用,而且在fish類的構造函數調用之前被調用。當然,這也很好理解,沒有父親就沒有孩子,因為fish類從animal類繼承而來,所以在fish類的對象構造之前,animal類的對象要先構造。在析構時,正好相反。
圖2.11 EX06.CPP程序的運行結果