星標公眾號,讓嵌入式知識 “投喂” 不停歇!
繼承就像家族遺傳——孩子會繼承父母的某些特征(如眼睛顏色、血型),同時又有自己的獨特之處。
在C++中:
// 基類
class 基類名 {
// 成員變量和成員函數
};
// 派生類
class 派生類名 : 繼承方式 基類名 {
// 派生類自己的成員
};
#include <iostream>
#include <string>
usingnamespacestd;
// 基類:動物
class Animal {
protected: // 保護成員,后面會解釋
string name;
int age;
public:
// 構造函數
Animal(string n, int a) : name(n), age(a) {}
// 動物共有的方法
void eat() {
cout << name << "在吃東西" << endl;
}
void sleep() {
cout << name << "在睡覺" << endl;
}
};
// 派生類:狗,繼承自動物
class Dog :public Animal {
public:
// 派生類的構造函數
Dog(string n, int a) : Animal(n, a) {}
// 狗特有的方法
void bark() {
cout << name << "在汪汪叫" << endl;
}
};
int main() {
// 創建一個Dog對象
Dog myDog("旺財", 3);
// 調用繼承來的方法
myDog.eat(); // 繼承自動物類
myDog.sleep(); // 繼承自動物類
// 調用自己特有的方法
myDog.bark(); // Dog類自己的方法
return0;
}
運行結果:
旺財在吃東西
旺財在睡覺
旺財在汪汪叫
代碼解釋:
Dog類通過: public Animal繼承了Animal類Dog自動獲得了name、age屬性和eat()、sleep()方法Dog還添加了自己特有的bark()方法Dog對象時,通過: Animal(n, a)調用了基類的構造函數
比如要設計各種智能設備:
開啟() 和 關閉()開啟() 和 關閉(),還能 調節亮度()開啟() 和 關閉(),還能 設置溫度()如果每個設備都從頭開始寫代碼,你會發現自己一直在重復寫 開啟() 和 關閉() 這兩個功能。
這就是繼承的價值所在! 我們可以創建一個"家電老祖宗"(基類),包含所有家電都有的功能,然后讓具體的設備(子類)繼承它。

C++有三種繼承方式,它們決定了基類成員在派生類中的訪問權限:
注意:基類的private成員任何時候都不能被派生類直接訪問,就像父母的隱私不會告訴孩子一樣。
class Base {
public:
int publicVar;
protected:
int protectedVar;
private:
int privateVar;
};
// 公有繼承
class Derived :public Base {
public:
void test() {
publicVar = 1; // 可以訪問
protectedVar = 2; // 可以訪問
// privateVar = 3; // 錯誤,不能訪問基類的私有成員
}
};
int main() {
Derived d;
d.publicVar = 10; // 可以訪問
// d.protectedVar = 20; // 錯誤,類外不能訪問保護成員
return0;
}
class Derived : protected Base {
public:
void test() {
publicVar = 1; // 可以訪問(現在是保護成員)
protectedVar = 2; // 可以訪問(現在是保護成員)
// privateVar = 3; // 錯誤
}
};
int main() {
Derived d;
// d.publicVar = 10; // 錯誤,現在是保護成員,類外不能訪問
return0;
}
class Derived : private Base {
public:
void test() {
publicVar = 1; // 可以訪問(現在是私有成員)
protectedVar = 2; // 可以訪問(現在是私有成員)
// privateVar = 3; // 錯誤
}
};
int main() {
Derived d;
// d.publicVar = 10; // 錯誤,現在是私有成員,類外不能訪問
return0;
}
可以把這三種繼承方式想象成:
當創建派生類對象時:
就像先有父母,才有孩子一樣。
#include <iostream>
usingnamespacestd;
class Base {
public:
Base() {
cout << "基類構造函數被調用" << endl;
}
};
class Derived :public Base {
public:
Derived() {
cout << "派生類構造函數被調用" << endl;
}
};
int main() {
Derived d; // 創建派生類對象
return0;
}
運行結果:
基類構造函數被調用
派生類構造函數被調用
如果基類有帶參數的構造函數,派生類必須顯式調用它:
#include <iostream>
#include <string>
usingnamespacestd;
class Person {
protected:
string name;
int age;
public:
// 基類帶參數的構造函數
Person(string n, int a) : name(n), age(a) {
cout << "Person構造函數" << endl;
}
};
class Student :public Person {
private:
int id;
public:
// 派生類構造函數,必須調用基類構造函數
Student(string n, int a, int i) : Person(n, a), id(i) {
cout << "Student構造函數" << endl;
}
void showInfo() {
cout << "姓名:" << name << ", 年齡:" << age << ", 學號:" << id << endl;
}
};
int main() {
Student s("張三", 18, 1001);
s.showInfo();
return0;
}
代碼解釋:
Student類的構造函數通過: Person(n, a)顯式調用了Person類的構造函數Student對象時,先正確初始化繼承來的name和age當銷毀派生類對象時:
與構造函數的順序相反。
#include <iostream>
usingnamespacestd;
class Base {
public:
Base() { cout << "基類構造函數" << endl; }
~Base() { cout << "基類析構函數" << endl; } // 析構函數
};
class Derived :public Base {
public:
Derived() { cout << "派生類構造函數" << endl; }
~Derived() { cout << "派生類析構函數" << endl; } // 析構函數
};
int main() {
Derived d; // 創建對象
return0; // 函數結束時對象被銷毀
}
運行結果:
基類構造函數
派生類構造函數
派生類析構函數
基類析構函數

在嵌入式系統中,構造和析構不僅僅是內存分配,還涉及到硬件初始化和資源釋放。

當出現以下繼承關系時,會產生"菱形繼承"問題:

在這種結構中,D類會通過B和C兩條路徑繼承A類的成員,導致D對象中會有兩份A類的成員,造成數據冗余和二義性。
#include <iostream>
usingnamespacestd;
class A {
public:
int x;
A() : x(10) {}
};
class B :public A {};
class C :public A {};
class D :public B, public C {};
int main() {
D d;
// cout << d.x; // 錯誤!編譯器不知道是B::x還是C::x
cout << d.B::x << endl; // 輸出10
cout << d.C::x << endl; // 輸出10
return0;
}
虛繼承可以解決菱形繼承問題,確保派生類只保留一份間接基類的成員。
#include <iostream>
usingnamespacestd;
class A {
public:
int x;
A() : x(10) {}
};
// 使用虛繼承
class B :virtualpublic A {};
class C :virtualpublic A {};
class D :public B, public C {};
int main() {
D d;
cout << d.x << endl; // 現在正確了,輸出10
return0;
}
代碼解釋:
virtual關鍵字,B和C虛繼承自AD類中就只有一份A類的成員,解決了二義性問題可以把虛繼承想象成:一個家族中,如果多個親戚都從同一個祖先那里繼承了財產,虛繼承確保這些財產在家族后代中只保留一份,避免重復。
繼承是面向對象編程的三大特性(封裝、繼承、多態)之一,掌握繼承可以幫助你編寫更簡潔、更易維護的代碼。就像現實世界中,我們站在巨人的肩膀上不斷進步一樣,編程中的繼承也讓我們可以基于已有代碼不斷構建更復雜的功能。
如果覺得有幫助,歡迎點贊、在看、轉發三連。我篩選了一些非常實用的嵌入式書籍,有需要的朋友可掃碼購買:

猜你喜歡:
這幾個嵌入式軟件開源項目值得深度復刻!
嵌入式Linux多線程編程注意事項
常見嵌入式軟件崩潰類型:12種典型場景!
嵌入式中代碼執行時間測量的幾種方法!
點擊閱讀原文,查看我給大家篩選的熱門嵌入式書籍!