C++中繼承的概念和定義
1.繼承的概念及定義
1.1繼承的概念
繼承機制是面向?qū)ο蟪绦蛟O(shè)計使代碼可以復(fù)用的最重要的手段,它允許程序員在保持原有類特性的基礎(chǔ)上進(jìn)行擴展,增加功能,這樣產(chǎn)生新的類,稱派生類。繼承呈現(xiàn)了面向?qū)ο蟪绦蛟O(shè)計的層次結(jié)構(gòu),體現(xiàn)了由簡單到復(fù)雜的認(rèn)知過程。以前我們接觸的復(fù)用都是函數(shù)復(fù)用,繼承是類設(shè)計層次的復(fù)用。
1.2繼承的定義格式

1.3繼承基類成員訪問方式的變化

(1)公有繼承
基類的公有成員,子類可以繼承為自己的公有成員。在派生類可以訪問,在外部也可以訪問。
基類的保護(hù)成員,子類可以繼承為自己的保護(hù)成員,在派生類可以訪問,在外部不可以訪問。
基類的私有成員,子類不可以訪問基類的私有成員。
(2)保護(hù)繼承
基類公有成員,子類中繼承為自己的保護(hù)成員,在派生類可以訪問,在外部不可以訪問。
基類保護(hù)成員,子類中繼承為自己的保護(hù)成員,在派生類可以訪問,在外部不可以訪問。
基類私有成員,子類不可以訪問基類的私有成員。
(3)私有繼承
基類公有成員,子類中繼承為自己的私有成員,在派生類可以訪問,在外部不可以訪問。
基類保護(hù)成員,子類中繼承為自己的私有成員,在派生類可以訪問,在外部不可以訪問。
基類私有成員,子類不可以訪問基類的私有成員。
1.4總結(jié)

(1)基類private成員任何方式繼承在派生類中都是不可見的。不可見指派生類對象不能去訪問它,但是基類的私有成員還是被繼承到了派生類對象中。
(2)基類的public成員和protected成員任何繼承方式在派生類都可以訪問。
(3)基類pretected成員,派生類可以訪問,類外不能訪問。
(4)基類的其他成員在子類的訪問方式 == Min(成員在基類的訪問限定符,繼承方式)。public > protected > private。
(5)使用關(guān)鍵字class時默認(rèn)的繼承方式是private,使用struct時默認(rèn)的繼承方式是public,不過最好顯示的寫出繼承方式。
class Derived : public Base //指明繼承方式是public class Derived : Base //沒寫的情況下是private struct Derived : Base //沒寫的情況下是public
(6)在實際運用中一般使用都是public繼承,幾乎很少使用protetced/private繼承,實際中
擴展維護(hù)性不強。
2.基類和派生類對象賦值轉(zhuǎn)換
派生類對象可以賦值給基類的對象 / 基類的指針 / 基類的引用。
基類對象不能賦值給派生類對象
基類的指針可以通過強制類型轉(zhuǎn)換賦值給派生類的指針。但是必須是基類的指針是指向派生類對象時才是安全的。
class Person //基類/父類
{
protected :
string _name; // 姓名
string _sex; // 性別
int _age; // 年齡
};
class Student : public Person //派生類/子類
{
public :
int _No ; // 學(xué)號
};
void Test ()
{
Student sobj ; //創(chuàng)建子類對象sobj
// 1.子類對象可以賦值給父類對象/指針/引用
Person pobj = sobj ;
Person* pp = &sobj;
Person& rp = sobj;
//2.基類對象不能賦值給派生類對象
sobj = pobj; //錯誤
// 3.基類的指針可以通過強制類型轉(zhuǎn)換賦值給派生類的指針
pp = &sobj
Student* ps1 = (Student*)pp; // 這種情況轉(zhuǎn)換時可以的。
ps1->_No = 10;
pp = &pobj;
Student* ps2 = (Student*)pp; // 這種情況轉(zhuǎn)換時雖然可以,但是會存在越界訪問的問題
ps2->_No = 10;
}
3.繼承中的作用域
在繼承體系中基類和派生類都有獨立的作用域。
子類和父類中有同名成員,子類成員將屏蔽父類對同名成員的直接訪問,這種情況叫隱藏,也叫重定義。(在子類成員函數(shù)中,可以使用 基類::基類成員 顯示訪問)
需要注意的是如果是成員函數(shù)的隱藏,只需要函數(shù)名相同就構(gòu)成隱藏。
注意在實際中在繼承體系里面最好不要定義同名的成員。
// B中的fun和A中的fun不是構(gòu)成重載,因為不是在同一作用域
// B中的fun和A中的fun構(gòu)成隱藏,成員函數(shù)滿足函數(shù)名相同就構(gòu)成隱藏。
class A //基類
{
public:
void fun()
{
cout << "func()" << endl;
}
};
class B : public A //派生類
{
public:
void fun(int i)
{
A::fun();
cout << "func(int i)->" <<i<<endl;
}
};
void Test()
{
B b;
b.fun(10);
};
//如果通過子類對象調(diào)用相同名稱的成員時,優(yōu)先訪問子類的,基類同名的成員永遠(yuǎn)無法通過
// 子類對象直接調(diào)用到,相當(dāng)于子類同名成員將基類的同名成員隱藏了
// 如果想要同名子類對象訪問基類中同名的成員,只需在成員前加上基類名稱::
// 如果在子類成員函數(shù)中,想要訪問基類同名的成員,只需在基類成員前加上基類名稱::
class Base //基類
{
public:
void SetBase(int b)
{
_b = b;
}
void fun()
{
cout << "Base::fun()" << endl;
}
public:
int _b;
char _c;
};
class Derived : public Base //派生類
{
public:
void SetDeirved(int b, int d)
{
_c = 100;
Base::_c = 100; //如果在子類成員函數(shù)中,想要訪問基類同名的成員,只需在基類成員前加上基類名稱::
__super::_c = 100;
SetBase(b);
_d = d;
}
void fun(int a)
{
cout << "Derived::fun(int)" << endl;
}
public:
int _d;
int _c;
};
int main()
{
Base b;
b.SetBase(10);
Derived d;
d.SetDeirved(100, 200);
/*
如果子類和基類中具有相同名稱的成員變量時,不管成員變量的類型是否相同,
都優(yōu)先訪問子類的同名成員變量
不能通過子類對象直接訪問子類和父類中同名的成員變量,就相當(dāng)與子類同名的成員變量將基類的同名成員變量隱藏了
*/
d._c = 'A'; // d對象中有兩個_c
// 有些情況下可能需要通過子類對象訪問基類中同名的成員變量
d.Base::_c = 'B';
// d.fun(); // 編譯報錯
d.fun(10);
d.Base::fun(); //如果想要同名子類對象訪問基類中同名的成員,只需在成員前加上基類名稱::
return 0;
}
總結(jié)
本篇文章就到這里了,希望能給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
C/C++ Qt 基本文件讀寫的基本使用(2種實現(xiàn))
文件的讀寫是很多應(yīng)用程序具有的功能,本文主要介紹了兩種實現(xiàn)方法,第一種使用QFile類的IODevice讀寫功能直接讀寫,第二種是利用 QFile和QTextStream結(jié)合起來,用流的方式進(jìn)行文件讀寫2021-11-11
深入const int *p與int * const p的區(qū)別詳解(常量指針與指向常量的指針)
本篇文章是對const int *p與int * const p的區(qū)別進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06
C語言詳細(xì)分析宏定義與預(yù)處理命令的應(yīng)用
宏定義是用宏名來表示一個字符串,在宏展開時又以該字符串取代宏名,這只是一種簡單的替換。字符串中可以含任何字符,可以是常數(shù),也可以是表達(dá)式,預(yù)處理程序?qū)λ蛔魅魏螜z查,如有錯誤,只能在編譯已被宏展開后的源程序時發(fā)現(xiàn)2022-07-07

