国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

面向?qū)ο蟮娜筇匦灾^承(C++)

這篇具有很好參考價值的文章主要介紹了面向?qū)ο蟮娜筇匦灾^承(C++)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

繼承的概念和定義

概念

??繼承機制是面向?qū)ο缶幘幊淌勾a可以復用的最重要的手段,它允許程序員在保持原有類特性的基礎(chǔ)上進行擴展,增加功能,這樣產(chǎn)生新的類,稱為派生類。繼承呈現(xiàn)了面向?qū)ο蟪绦蛟O(shè)計的層次結(jié)構(gòu),體現(xiàn)了由簡單到復雜的認知過程。繼承是類設(shè)計層次的復用。

#include <iostream>
#include <string>

using namespace std;

class Person
{
public:
	void Print()
	{
		cout << "name:" << _name << endl;
		cout << "age:" << _age << endl;
	}
protected:
	string _name = "peter"; // 姓名
	int _age = 18;			// 年齡
};
class Student : public Person
{
protected:
	int _stuid; // 學號
};
class Teacher : public Person
{
	int _jobid; // 工號
};
int main()
{
	Student s;
	Teacher t;
	s.Print();
	t.Print();

	return 0;
}

定義

定義格式

??clas 派生類(子類) : 繼承方式 基類(父類)

繼承關(guān)系和訪問限定符

??繼承方式:public繼承、protected繼承、private繼承
??訪問限定符:public訪問、protected訪問、private訪問

繼承基類成員訪問方式的變化
類成員/繼承方式 public繼承 protected繼承 private繼承
基類的public成員 派生類的public成員 派生類的protected成員 派生類的private成員
基類的protected成員 派生類的protected成員 派生類的protected成員 派生類的private成員
基類的private成員 在派生類中不可見 在派生類中不可見 在派生類中不可見
  1. 基類private成員在派生類中無論以什么方式繼承都是不可見的。不可見是指基類的私有成員還是被繼承到了派生類對象中,但是語法上限制派生類對象不管在類里面還是類外面都不能去訪問它。
  2. 基類private成員在派生類中是不能被訪問的,如果基類成員不想在類外直接被訪問,但需要在派生類中能訪問,就定義為protected??梢钥闯霰Wo成員限定符是因繼承才出現(xiàn)的。
  3. 使用關(guān)鍵字class時默認的繼承方式是private,使用struct時默認的繼承方式是public,不過最好顯示的寫出繼承方式。
  4. 在實際運用中一般使用都是public繼承,幾乎很少使用protected/private繼承,也不提倡使用protected/private繼承,因為protected/private繼承,因為protected/private繼承下來的成員都只能在派生類的類里面使用,實際中擴展維護性不強。
class Person
{
public:
	void Print()
	{
		cout << _name << endl;
	}
protected:
	string _name = "張三";
private:
	int _age = 18;
};
//class Student : private Person
//class Student : protected Person
class Student : public Person
{
protected:
	int _stunum;
};
int main()
{
	Student s;
	s.Print();

	return 0;
}

面向?qū)ο蟮娜筇匦灾^承(C++)

基類和派生類對象賦值轉(zhuǎn)換

??派生類對象可以賦值給 基類的對象/基類的指針/基類的引用。這種操作被叫做切片或者切割,意思是把派生類中父類的部分切割賦值過去(并沒有真正的切割)。
面向?qū)ο蟮娜筇匦灾^承(C++)

??基類對象不能賦值給派生類對象。
??基類的指針或者引用可以通過強制類型轉(zhuǎn)換賦值給派生類的指針或者引用。但是必須是基類的指針指向派生類對象時才是安全的。如果基類是多態(tài)類型,可以使用RTTI來進行識別后進行安全轉(zhuǎn)換。

class Person
{
protected:
	string _name;
	string _sex;
	int _age;
};
class Student : public Person
{
public:
	int _No; // 學號
};
void Test()
{
	Student sobj;
	// 1.子類對象可以賦值給父類對象/指針/引用
	Person pobj = sobj;
	Person* pp = &sobj;
	Person& rp = sobj;

	// 2.基類對象不能賦值給派生類對象
	//sobj = pobj;

	// 3.基類的指針可以通過強制類型轉(zhuǎn)換賦值給派生類的指針
	pp = &sobj;
	Student* ps1 = (Student*)pp;
	ps1->_No = 10;

	//pp = &pobj;
	//Student* ps2 = (Student*)pp;// 這種情況也可以轉(zhuǎn)換,但是可能會造成訪問越界
	//ps2->_No = 10;
}
int main()
{
	Test();

	return 0;
}

面向?qū)ο蟮娜筇匦灾^承(C++)

面向?qū)ο蟮娜筇匦灾^承(C++)

繼承中的作用域

  1. 在繼承體系中基類和派生類都有獨立的作用域。
  2. 子類和父類中有同名成員,子類成員將屏蔽父類對同名成員的直接訪問,這種情況叫隱藏,也叫作重定義。(在子類成員函數(shù)中,可以使用 基類::積累成員 來進行顯示訪問)
  3. 需要注意的是如果成員函數(shù)是隱藏的,只需要函數(shù)名相同就能構(gòu)成隱藏。
  4. 實際開發(fā)中盡量不要在繼承體系里面定義同名的成員。
class Person
{
protected:
	string _name = "張三";
	int _num = 5107;	// 身份證號
};
class Student : public Person
{
public:
	void Print()
	{
		// Student的_num和Person的_num構(gòu)成隱藏關(guān)系
		cout << "name:" << _name << endl;
		cout << "ID:" << Person::_num << endl;
		cout << "sno:" << _num << endl;
	}
protected:
	int _num = 111; // 學號
};
int main()
{
	Student s1;
	s1.Print();

	return 0;
}
// B中的fun和A中的fun不構(gòu)成重載,因為不在同一個作用域
// B中的fun和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;
	}
};
int main()
{
	B b;
	b.fun(10);
	b.A::fun();

	return 0;
}

面向?qū)ο蟮娜筇匦灾^承(C++)

派生類的默認成員函數(shù)

??派生類的默認成員函數(shù),即使我們不寫,編譯器也會默認生成一個。

  1. 派生類的構(gòu)造函數(shù)必須調(diào)用基類的構(gòu)造函數(shù)初始化基類的那一部分成員。如果基類沒有默認的構(gòu)造函數(shù),則必須在派生類構(gòu)造函數(shù)的初始化列表階段顯示調(diào)用;
  2. 派生類的拷貝構(gòu)造函數(shù)必須調(diào)用基類的拷貝構(gòu)造完成基類的拷貝初始化;
  3. 派生類的operator=必須調(diào)用基類的operator=來完成基類的復制;
  4. 派生類的析構(gòu)函數(shù)會在被調(diào)用完成后自動調(diào)用基類的析構(gòu)函數(shù)清理基類成員。因為這樣才能保證派生類對象先清理派生類成員再清理基類成員的順序;
  5. 派生類對象初始化先調(diào)用基類構(gòu)造再調(diào)用派生類構(gòu)造;
  6. 派生類對象析構(gòu)清理先調(diào)用派生類析構(gòu)再調(diào)用基類的析構(gòu);
    面向?qū)ο蟮娜筇匦灾^承(C++)
class Person
{
public:
	Person(const char* name = "peter")
		: _name(name)
	{
		cout << "Person()" << endl;
	}
	Person(const Person& p)
		: _name(p._name)
	{
		cout << "Person(const Person& p)" << endl;
	}
	Person& operator=(const Person& p)
	{
		cout << "Person operator=(const Person& p" << endl;
		if (this != &p)
			_name = p._name;

		return *this;
	}
	~Person()
	{
		cout << "~Person()" << endl;
	}
protected:
	string _name;
};
class Student : public Person
{
public:
	Student(const char* name, int num)
		: Person(name)
		, _num(num)
	{
		cout << "Student()" << endl;
	}
	Student(const Student& s)
		:Person(s)
		, _num(s._num)
	{
		cout << "Student(const Student& s)" << endl;
	}
	Student& operator= (const Student& s)
	{
		cout << "Student& operator= (const Student& s)" << endl;
		if (this != &s)
		{
			Person::operator=(s);
			_num = s._num;
		}
		return *this;
	}
	~Student()
	{
		cout << "~Student()" << endl;
	}
protected:
	int _num;
};
int main()
{
	Student s1("jack", 18);
	Student s2(s1);
	Student s3("rose", 17);
	s1 = s3;

	return 0;
}

面向?qū)ο蟮娜筇匦灾^承(C++)面向?qū)ο蟮娜筇匦灾^承(C++)

繼承與友元

??友元關(guān)系不能繼承,也就是說基類友元不能訪問子類的私有和保護成員。如果需要訪問,就需要在定義成子類的友元。

class Student;
class Person
{
public:
	friend void Display(const Person& p, const Student& s);
protected:
	string _name;
};
class Student : public Person
{
public:
	friend void Display(const Person& p, const Student& s);
protected:
	int _stuNum;
};
void Display(const Person& p, const Student& s)
{
	cout << p._name << endl;
	cout << s._stuNum << endl;
}
int main()
{
	Person p;
	Student s;
	Display(p, s);

	return 0;
}

面向?qū)ο蟮娜筇匦灾^承(C++)

繼承與靜態(tài)成員

??基類定義了static靜態(tài)成員,則整個繼承體系里面只有一個這樣的成員。無論派生出都少個派生類,都只有一個static成員實例。

class Person
{
public:
	Person()
	{
		++_count;
	}
protected:
	string _name;
public:
	static int _count;
};
int Person::_count = 0;
class Student : public Person
{
protected:
	int _stuNum;
};
class Graduate : public Student
{
protected:
	string _seminarCourse;
};
int main()
{
	Student s1;
	Student s2;
	Student s3;
	Graduate s4;
	cout << "人數(shù):" << Person::_count << endl;
	Student::_count = 0;
	cout << "人數(shù):" << Person::_count << endl;

	return 0;
}

面向?qū)ο蟮娜筇匦灾^承(C++)

菱形繼承與虛擬繼承

菱形繼承

??單繼承:一個派生類只有一個直接基類的時候,就稱這種繼承是單繼承。
面向?qū)ο蟮娜筇匦灾^承(C++)

??多繼承:一個子類有兩個或兩個以上的父類時,就稱這種繼承為多繼承。
面向?qū)ο蟮娜筇匦灾^承(C++)

??菱形繼承:菱形繼承是多繼承的一種特殊情況。
面向?qū)ο蟮娜筇匦灾^承(C++)

??菱形繼承會造成數(shù)據(jù)冗余和二義性。

class Person
{
public:
	string _name;
};
class Student : public Person
{
protected:
	int _num;
};
class Teacher : public Person
{
protected:
	int _id;
};
class Assistant : public Student, public Teacher
{
protected:
	string _majorCourse;
};
int main()
{
	Assistant a;

	a.Student::_name = "張三";
	a.Teacher::_name = "李四";

	return 0;
}

??二義性需要指定訪問哪個父類成員,不然不知道訪問哪個。
??數(shù)據(jù)冗余指的是內(nèi)存中保存了兩個數(shù)據(jù),這兩個數(shù)據(jù)應該是相同的。
面向?qū)ο蟮娜筇匦灾^承(C++)

虛擬繼承

??虛擬繼承被用來解決菱形繼承導致的數(shù)據(jù)冗余和二義性問題。

class A
{
public:
	int _a;
};
class B : public A
//class B : virtual public A
{
public:
	int _b;
};
class C : public A
//class C : virtual public A
{
public:
	int _c;
};
class D : public B, public C
{
public:
	int _d;
};
int main()
{
	D d;
	d.B::_a = 1;
	d.C::_a = 2;
	d._b = 3;
	d._c = 4;
	d._d = 5;

	return 0;
}

面向?qū)ο蟮娜筇匦灾^承(C++)

面向?qū)ο蟮娜筇匦灾^承(C++)

??由上圖可以得出,D對象中將A放到了對象組的最下面,這個A屬于B和C。這里B和C中有兩個指針,指向一張表。這兩個指針叫做虛基表指針,這兩個表叫做虛基表。虛基表中存放的是偏移量,通過偏移量可以找到A。
面向?qū)ο蟮娜筇匦灾^承(C++)

繼承的總結(jié)與反思

??多繼承是C++語言復雜度的典型體現(xiàn)。因為有多繼承就會導致菱形繼承的問題出現(xiàn),菱形繼承就會導致數(shù)據(jù)冗余和二義性,為了解決這些問題就需要 引入了虛擬繼承,這是很復雜的。所以在我們平時編寫代碼時,要盡量避免菱形繼承的出現(xiàn)。
??多繼承被公認為是C++的缺陷之一,盡管它在邏輯上是合理的。后來很多OO(面向?qū)ο螅┱Z言都都沒有采用C++的多繼承,比如JAVA。

繼承和組合

??public繼承是一種is-a的關(guān)系,也就是每個派生類對象都是一個基類對象;組合是中has-a的關(guān)系,假設(shè)B組合了A,每個B對象中都有一個A對象。
??在編程開發(fā)中有限使用對象組合,而不是選擇類繼承。
??繼承允許根據(jù)基類的實現(xiàn)來定義派生類的實現(xiàn)。這種通過生成派生類的復用通常被稱為白箱復用。白箱是相對于可視性而言的,在繼承方式中,基類的內(nèi)部細節(jié)對子類可見。繼承在一定程度上破壞了基類的封裝,基類的改變,對派生類有很大的影響。派生類和基類間的依賴關(guān)系很強,耦合度高。
??對象組合是類繼承之外的另一種復用選擇。新的更為復雜的功能可以通過組裝或組合對象來獲得。對象組合要求被組合的對象具有良好定義的接口。這種復用風格被稱為黑箱復用,因為對象的內(nèi)部細節(jié)是不可見的。對象只以黑箱的形式出現(xiàn)。組合類之間沒有很強的依賴關(guān)系,耦合度低。有限使用對象組合有助于保持每個類的封裝性。
??實際盡量多去用組合。組合的耦合度低,代碼維護性好。不過繼承也有用武之地的,有些關(guān)系就適合繼承那就用繼承,另外要實現(xiàn)多態(tài),也必須要繼承。類之間的關(guān)系可以用繼承,可以用組合,就用組合。文章來源地址http://www.zghlxwxcb.cn/news/detail-458374.html

// Car和BMW Car和Benz構(gòu)成is-a的關(guān)系
class Car
{
protected:
	string _colour = "白色";
	string _num = "川ANB666";
};
class BMW : public Car
{
public:
	void Drive()
	{
		cout << "好開-操控" << endl;
	}
};
class Benz : public Car
{
public:
	void Drive()
	{
		cout << "好坐-舒適" << endl;
	}
};
// Tire和Car構(gòu)成has-a的關(guān)系
class Tire
{
protected:
	string _brand = "Michelin";
	size_t _size = 17;
};
class Car
{
protected:
	string _colour = "白色";
	string _num = "川ANB666";
	Tire _t;
};

到了這里,關(guān)于面向?qū)ο蟮娜筇匦灾^承(C++)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務器費用

相關(guān)文章

  • Java面向?qū)ο?3——三大特性之繼承

    Java面向?qū)ο?3——三大特性之繼承

    繼承就是 Java 允許我們用 extends ,讓一個類與另一個類建立起一種父子關(guān)系; 被繼承的類稱為父類(基類、超類),繼承父類的類都稱為子類(派生類), 當子類繼承父類后,就可以直接使用父類公共的屬性和方法了 當子類繼承父類后,就可以直接使用父類公共的屬

    2024年04月27日
    瀏覽(27)
  • 【JAVASE】帶你了解面向?qū)ο笕筇匦灾唬ɡ^承)

    【JAVASE】帶你了解面向?qū)ο笕筇匦灾唬ɡ^承)

    ?作者簡介:大家好,我是橘橙黃又青,一個想要與大家共同進步的男人???? ??個人主頁:再無B~U~G-CSDN博客 Java 中使用類對現(xiàn)實世界中實體來進行描述,類經(jīng)過實例化之后的產(chǎn)物對象,則可以用來表示現(xiàn)實中的實體,但是現(xiàn)實世界錯綜復雜,事物之間可能會存在一些關(guān)

    2024年04月09日
    瀏覽(26)
  • C++ 面向?qū)ο笕筇匦浴鄳B(tài)

    C++ 面向?qū)ο笕筇匦浴鄳B(tài)

    ?1主頁:我的代碼愛吃辣 ??2知識講解:C++ 繼承 ??3開發(fā)環(huán)境:Visual Studio 2022 ??4前言:面向?qū)ο笕筇匦缘?,封裝,繼承,多態(tài),今天我們研究研究 C++的多態(tài) 。 目錄 一.多態(tài)的概念 二.多態(tài)的定義及實現(xiàn) 1.多態(tài)的構(gòu)成條件 2. 虛函數(shù) 3.虛函數(shù)的重寫 4. C++11 override 和 fina

    2024年02月12日
    瀏覽(92)
  • C++核心編程—類和對象,類的三大特性——封裝、繼承、多態(tài)

    C++核心編程—類和對象,類的三大特性——封裝、繼承、多態(tài)

    縱有疾風起,人生不言棄。本文篇幅較長,如有錯誤請不吝賜教,感謝支持。 ①什么是對象? 生活中有各種各樣的 事物 ,如人、動物、植物等在C++中將這些稱為對象。 對象多種多樣, 各種對象的屬性也不相同 。 例如狗的品種,毛色,年齡等 各個對象都有自己的行為 ,例

    2024年02月07日
    瀏覽(29)
  • 面向?qū)ο笤斀猓嫦驅(qū)ο蟮娜筇卣鳎悍庋b、繼承、多態(tài)

    面向?qū)ο笤斀?,面向?qū)ο蟮娜筇卣鳎悍庋b、繼承、多態(tài)

    一、面向?qū)ο笈c面向過程 面向?qū)ο缶幊?(Object-Oriented Programming,簡稱OOP)和 面向過程編程 (Procedural Programming,簡稱PP)是兩種不同的 編程范式 。 面向?qū)ο缶幊虖娬{(diào)把問題分解成對象,通過封裝、繼承和多態(tài)等機制,來處理對象之間的關(guān)系 。每個對象都可以獨立地處理自

    2024年02月21日
    瀏覽(23)
  • 【面向?qū)ο笳Z言三大特性之 “多態(tài)”】

    【面向?qū)ο笳Z言三大特性之 “多態(tài)”】

    目錄 ?1. 多態(tài)的概念 1.1 概念 2. 多態(tài)的定義及實現(xiàn) 2.1多態(tài)的構(gòu)成條件 2.2 虛函數(shù) ?2.3虛函數(shù)的重寫 2.4 C++11 override 和 final ?2.5 重載、覆蓋(重寫)、隱藏(重定義)的對比 ?3. 抽象類 3.1 概念 3.2 接口繼承和實現(xiàn)繼承 ?4.多態(tài)的原理 4.1虛函數(shù)表 ?4.2多態(tài)的原理 4.3 動態(tài)綁定與靜態(tài)綁定

    2023年04月17日
    瀏覽(56)
  • 面向?qū)ο笕筇匦灾弧@承(上篇)

    面向?qū)ο笕筇匦灾弧@承(上篇)

    目錄 前文 一.什么是継承? 1.1 継承的定義 1.2 継承的格式 1.2.1 継承的使用格式 1.2.2 継承關(guān)系和訪問限定符 二,基類和派生類對象復制轉(zhuǎn)換 三,継承中的作用域 四,派生類/子類中的默認成員函數(shù) 六,継承與友元 ?六,継承與靜態(tài)成員 總結(jié) 本篇文章主要是詳解面向?qū)ο笕?/p>

    2024年02月03日
    瀏覽(19)
  • Unity-C# (面向?qū)ο笕筇匦?

    Unity-C# (面向?qū)ο笕筇匦?

    傳值調(diào)用和引用調(diào)用 輸出:11 傳值調(diào)用中形參為一個新的臨時變量,賦值由實參拷貝而來,只是賦予了與實參一樣的值所以在函數(shù)體內(nèi)部修改并不會影響實參 輸出:22 引用調(diào)用時,形參拷貝的是實參的地址,二者指向同一個堆空間,所以形參改變會對實參造成影響 輸出:

    2024年04月09日
    瀏覽(24)
  • 【java】面向?qū)ο笕筇匦灾鄳B(tài)

    【java】面向?qū)ο笕筇匦灾鄳B(tài)

    ? ? ? ? 俗話說的好,“一龍生九子,九子各不同”,這句話就蘊含了面向?qū)ο笕筇匦灾坏亩鄳B(tài)的思想。那么多態(tài)具體有什么特點呢,就由博主來帶大家梳理一下吧?? 目錄 一、什么是多態(tài) 二、重寫 三、向上轉(zhuǎn)型和向下轉(zhuǎn)型 1、向上轉(zhuǎn)型 2、向下轉(zhuǎn)型 四、多態(tài)的優(yōu)缺點

    2024年03月15日
    瀏覽(24)
  • 【JAVASE】面向?qū)ο蟪绦蛉筇匦灾? 封裝)

    【JAVASE】面向?qū)ο蟪绦蛉筇匦灾? 封裝)

    ?作者簡介:大家好,我是橘橙黃又青,一個想要與大家共同進步的男人????n ??個人主頁:再無B~U~G-CSDN博客 目標: 1.包的使用 2.static的使用 3. 代碼塊概念以及分類 面向?qū)ο蟪绦蛉筇匦裕悍庋b、繼承、多態(tài) 。而類和對象階段,主要研究的就是封裝特性。何為

    2024年04月17日
    瀏覽(25)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包