C++中的繼承分爲三種繼承方式:
public,protected,private。
繼承會導致父類中的成員訪問屬性發生變化。
繼承機制中,子類訪問父類成員方式
不管什麼繼承,父類的private成員始終爲父類私有。
public繼承:父類的public和protected成員在子類中訪問屬性不變
private繼承:父類的public和protected成員在子類中變成private
protected繼承:父類public和protected成員在子類中變成protected
例子1:
class Base{
public:
Base()
{
printf(“Base構造函數\n”);
}
~Base()
{
printf(“Base析構函數\n”);
}
};
class Derive : public Base{
public:
Derive()
{
printf(“Derive構造函數\n”);
}
~Derive()
{
printf(“Derive析構函數\n”);
}
};
int main()
{
Base* d = new Derive();
delete d;
return 0;
}1234567891011121314151617181920212223242526272829303132
這段代碼輸出:
Base構造函數
Derive構造函數
Base析構函數123
分析:
主函數中Base* d = new Derive(),new一個Base類型的指針實例。
因爲子類是繼承父類的,所以調用子類的構造方法之前,必然會首先調用父類的構造方法(初始化父類的一些成員變量);
new出來的實例是Base類型的,所以delete時,會調用Base的析構函數。
例子2:
將例1中的主函數變爲:
Derive* d = new Derive();
delete d;12
輸出:
Base構造函數
Derive構造函數
Derive析構函數
Base析構函數1234
分析:
構造函數的調用順序與例1一樣,不同的是這次new出來的實例指向了Derive類型的指針,因爲Derive繼承了Base類中成員變量和函數,所以生成Derive類型實例的同時,必然會產生Base類型的實例。
根據析構函數的調用順序,先構造後析構,因此輸出結果如上。
例子3:
將例1中Base的析構函數改爲virtual函數:
virtual ~Base()
{
printf(“Base析構函數\n”);
}1234
輸出結果:
Base構造函數
Derive構造函數
Derive析構函數
Base析構函數1234
可以看出,輸出結果與例2一樣。
構造函數的調用順序與上面的例子一樣,這次因爲Base的析構函數成了虛函數,父類指針指向子類的實例,所以在調用父類的析構函數時,會有多態效果,實際調用的是子類的析構函數。
delete d的時候,先析構繼承類,再析構父類。
實際上,我們在使用類的析構函數時,一般都把析構函數設爲虛函數。
在實現多態時,當用基類操作派生類,在析構時防止只析構基類而不析構派生類的狀況發生。
例子4:
class Base{
public:
Base(int num)
{
num_ = num;
printf(“Base構造函數,num=%d\n”, num_);
}
~Base()
{
printf(“Base析構函數\n”);
}
virtual void Show()
{
printf(“Show:%d\n”,num_);
}
protected:
int num_;
};
class Derive : public Base{
public:
Derive(int num, int age):Base(num)
{
age_ = age;
printf(“Derive構造函數,age=%d\n”, age_);
}
~Derive()
{
printf(“Derive析構函數\n”);
}
void Show()
{
printf(“Show, num:%d, age:%d\n”, num_, age_);
}
private:
int age_;
int num_;
};
int main()
{
Base* d = new Derive(1,3);
d->Show();
delete d;
return 0;
}12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
輸出:
Base構造函數,num=1
Derive構造函數,age=3
Show, num:-842150451, age:3
Base析構函數1234
子類的成員變量和函數名是可以跟父類相同的。
繼承類的構造函數需要“繼承”基類的構造函數,因爲在構造子類時,必然要構造基類。
用:符號來“繼承”。
如:Derive(int num, int age):Base(num)
當繼承類的成員變量名與基類相同時,以繼承類爲準。
當基類的成員函數修飾爲virtual函數時,指向基類的繼承類實例調用函數時,調用的是繼承類的方法。