主頁 > 軟體設計 > C++--繼承(繼承的概念與定義、派生類默認成員函式、菱形繼承及菱形虛擬繼承)

C++--繼承(繼承的概念與定義、派生類默認成員函式、菱形繼承及菱形虛擬繼承)

2021-05-04 09:30:32 軟體設計

一、繼承的概念及定義

1、繼承的概念

繼承機制是面向物件程式設計使代碼可以復用的最重要的手段,它允許程式員在保持原有類特性的基礎上進行擴展,增加新的功能,這樣產生新的類,新類稱為派生類或基類,繼承是類設計層次的復用,呈現了面向物件程式設計的層次結構,

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{
protected:
	int _jobid;
};

int main() {
	Student s;
	Teacher t;
	s.Print();
	t.Print();
	return 0;
}

繼承后父類的Person的成員(成員函式+成員變數)都會變成子類的一部分,這里體現出了Student和Teacher復用了Person的成員,下面我們使用監視視窗查看Student和Teacher物件,可以看到變數的復用,呼叫Print可以看到成員函式的復用,
在這里插入圖片描述

2、繼承定義

2.1、定義格式

下面我們看到Person是父類(基類),Student是子類(派生類),

在這里插入圖片描述

2.2、繼承方式和訪問限定符

在這里插入圖片描述

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

類成員/繼承方式public繼承protected繼承private繼承
基類的public成員派生類的public成員派生類的protected成員派生類的private成員
基類的protected成員派生類的protected成員派生類的protected成員派生類的private成員
基類的private成員在派生類中不可見在派生類中不可見在派生類中不可見

總結:

1、基類private成員在派生類中無論以什么方式繼承都是不可見的,這里的不可見是指基類的私有成員在派生類中還是存在,但是語法上限制派生類物件不管在類里面還是類外面都不能去訪問它,

在這里插入圖片描述
但是我們還是可以呼叫Print方法列印_name的值,不可訪問是指我們不管在派生類里還是派生類外面都不可訪問,

2、基類private成員在派生類中是不能被訪問,如果基類成員不想在類外直接被訪問,但是需要在派生類中能被訪問,就定義為protected,可以看出保護成員限定符是因繼承才出現的,

3、除了基類的私有成員在子類中都是不可見的,基類的其他成員在子類的訪問方式=min(成員在基類的訪問限定符,繼承方式),權限:public>protected>private,

4、還需要注意:class的默認繼承方式是private,struct的默認繼承方式是public,

二、基類和派生類物件賦值轉換

  • 派生類物件可以賦值給基類的物件 / 基類的指標 / 基類的參考,稱為切割或切片,寓意把派生類中父類的那部分切來賦值過去,
  • 基類物件不能賦值給派生類,

在這里插入圖片描述

class Person
{
protected :
	string _name; // 姓名
	string _sex; // 性別
	int _age; // 年齡
};

class Student : public Person
{
public :
	int _No ; // 學號
};

int main()
{
	Student sobj ;
	// 1.子類物件可以賦值給父類物件/指標/參考
	Person pobj = sobj ;
	Person* pp = &sobj;
	Person& rp = sobj;
	
	//2.基類物件不能賦值給派生類物件
	//sobj = pobj;
	
	// 3.基類的指標可以通過強制型別轉換賦值給派生類的指標
	pp = &sobj
	
	Student* ps1 = (Student*)pp; // 這種情況轉換時可以的,因為pp本身就是指向一個Student*型別
	ps1->_No = 10;
	pp = &pobj;
	
	Student* ps2 = (Student*)pp; // 這種情況轉換時雖然可以,但是會存在越界訪問的問題
	ps2->_No = 10;
	return 0;
}

三、繼承中的作用域

  • 1、在繼承體系中基類和派生類都是獨立的作用域
  • 2、子類和父類中有同名成員時,子類成員將屏蔽父類對同名成員的直接訪問,這種情況叫隱藏(重定義),(在子類成員函式中,可以使用基類::基類成員 顯示訪問),
  • 3、對于成員函式的隱藏,只要函式名相同就構成隱藏,

成員屬性構成重定義:

// Student的_num和Person的_num構成隱藏關系,可以看出這樣代碼雖然能跑,但是非常容易混淆
class Person
{
protected :
	string _name = "小李子"; // 姓名
	int _num = 111; // 身份證號
};

class Student : public Person
{
public:
	void Print()
	{
		cout<<" 姓名:"<<_name<< endl;
		cout<<" 身份證號:"<<Person::_num<< endl;	//通過基類::基類成員  顯示訪問
		cout<<" 學號:"<<_num<<endl;
	}
protected:
	int _num = 999; // 學號
};
void Test()
{
	Student s1;
	s1.Print();
};

成員函式構成重定義:

// B中的fun和A中的fun不是構成多載,因為不是在同一作用域
// B中的fun和A中的fun構成隱藏,成員函式滿足函式名相同就構成重定義,
class A
{
public:
	void fun()
	{
		cout << "func()" << endl;
	}
};
class B : public A
{
public:
	void fun(int i)
	{
		cout<<"void fun(int i)"<<endl;
	}
};

void test(){
	B b;
	b.func(10);
}

四、派生類的默認成員函式

"默認"的意思就是指我們不寫,編譯器會為我們自動生成,那么在派生類中,編譯器主要為我們生成以下幾個默認成員函式:

4.1、建構式

派生類的建構式必須呼叫基類的建構式初始化基類的那一部分成員,不能自己顯示去初始化,如果基類沒有默認的建構式,則必須在派生類建構式的初始化串列階段顯示呼叫,派生類物件初始化先呼叫基類構造再呼叫派生類構造,

class Person{
public:
	Person(const char* name="peter")
		:_name(name)
	{
		cout<<"Person()"<<endl;
	}
protected:
	string _name;
}

class Student:public Person{
public:
	Student(const char* name,int num)
		:Person(name),_num(num)
	{
		cout<<"Student()"<<endl;
	}
protected:
	int _num;//學號
}

4.2、拷貝建構式

派生類的拷貝建構式必須呼叫基類的拷貝建構式完成基類的拷貝構造,

class Person{
public:
	Person(const Person& p )
		:_name(p._name)
	{
		cout<<"Person(const Person& p)"<<endl;
	}
protected:
	string _name;
}

class Student:public Person{
public:
	Student(const Student& s)
		:Person(s),_num(s._num)
	{
		cout<<"	Student(const Student& s)"<<endl;
	}
protected:
	int _num;//學號
}

4.3、賦值運算子多載函式

派生類的operator=必須要呼叫基類的operator=完成基類的復制,

class Person{
public:
	Person& operator=(const Person& p)
	{
		cout<<"Person operator=(const Person& p)"<< endl;
		if(this!=&p)
			_name=p._name;
		return *this;
	}
protected:
	string _name;
}

class Student:public Person{
public:
	Student& operator=(const Student& s)
	{
		cout<<"Student& operator= (const Student& s)"<< endl;
		if(this!=&s)
		{
			Person::operator=(s);	//要顯示指定呼叫父類的operator=,因為子類和父類構成重定義
			_num=s._num;
		}
		return *this;
	}
protected:
	int _num;//學號
}

4.4、解構式

派生類的解構式會在被呼叫完成后 自動呼叫基類的解構式清理基類的成員,因為這樣才能保證派生類物件先清理派生類成員再清理基類成員的順序,
派生類物件析構清理先呼叫派生類析構再呼叫基類的析構,

class Person{
public:
	~Person()
	{
		cout<<"~Person()"<<endl;
	}
protected:
	string _name;
}

class Student:public Person{
public:
	//兩個迷惑點:
		//1、子類的解構式和父類的解構式構成隱藏,所有類的解構式,名字會被統一處理成destructor
		//2、自己顯示呼叫,會存在父類先析構,不符合先構造先析構,后構造后析構的原則,
	~Student()
	{
		//Person::~Person(); 不要顯示呼叫,要保證子類先析構
		cout<<"	~Student()"<<endl;
	}
protected:
	int _num;//學號
}

編譯器在出作用域時自動呼叫父類的解構式,看以下匯編語言:

	~Student()
	{
008E3D50  push        ebp  
008E3D51  mov         ebp,esp  
008E3D53  push        0FFFFFFFFh  
008E3D55  push        8EAB30h  
008E3D5A  mov         eax,dword ptr fs:[00000000h]  
008E3D60  push        eax  
008E3D61  sub         esp,0CCh  
008E3D67  push        ebx  
008E3D68  push        esi  
008E3D69  push        edi  
008E3D6A  push        ecx  
008E3D6B  lea         edi,[ebp-0D8h]  
008E3D71  mov         ecx,33h  
008E3D76  mov         eax,0CCCCCCCCh  
008E3D7B  rep stos    dword ptr es:[edi]  
008E3D7D  pop         ecx  
008E3D7E  mov         eax,dword ptr [__security_cookie (08EF008h)]  
008E3D83  xor         eax,ebp  
008E3D85  push        eax  
008E3D86  lea         eax,[ebp-0Ch]  
008E3D89  mov         dword ptr fs:[00000000h],eax  
008E3D8F  mov         dword ptr [this],ecx  
008E3D92  mov         ecx,offset _6235FB68_testvecotr@cpp (08F202Ah)  
008E3D97  call        @__CheckForDebuggerJustMyCode@4 (08E1537h)  
		cout << "~Student()" << endl;
008E3D9C  mov         esi,esp  
008E3D9E  push        offset std::endl<char,std::char_traits<char> > (08E1055h)  
008E3DA3  push        offset string "~Student()" (08ECDF0h)  
008E3DA8  mov         eax,dword ptr [__imp_std::cout (08F00E0h)]  
008E3DAD  push        eax  
008E3DAE  call        std::operator<<<std::char_traits<char> > (08E12B2h)  
008E3DB3  add         esp,8  
008E3DB6  mov         ecx,eax  
008E3DB8  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (08F00A0h)]  
008E3DBE  cmp         esi,esp  
008E3DC0  call        __RTC_CheckEsp (08E13D9h)  
	}
008E3DC5  mov         ecx,dword ptr [this]  
008E3DC8  call        Person::~Person (08E1177h)  //當出了作用域時,編譯器自動呼叫父類的解構式

在這里插入圖片描述

五、繼承與友元

友元關系不能繼承,也就是說基類友元不能訪問子類私有和保護成員

在這里插入圖片描述

六、繼承與靜態成員

基類定義了static靜態成員,則整個繼承體系里面只有一個這樣的成員,無論派生多少個子類,都只有一個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 ; // 研究科目
};
void TestPerson()
{
	Student s1 ;
	Student s2 ;
	Student s3 ;
	Graduate s4 ;
	cout <<" 人數 :"<< Person ::_count << endl;
	Student ::_count = 0;
	cout <<" 人數 :"<< Person ::_count << endl;
}

//運行結果:
	人數 :4
	人數 :0

七、復雜的菱形繼承及菱形虛擬繼承

單繼承:一個子類只有一個直接父類時稱這個繼承關系為單繼承,

在這里插入圖片描述

多繼承:一個子類有兩個或以上直接父類時稱這個繼承關系為多繼承

在這里插入圖片描述

菱形繼承:菱形繼承是多繼承的一種特殊情況,

在這里插入圖片描述

菱形繼承的問題:從下面的物件成員模型構造,可以看出菱形繼承有資料冗余和二義性的問題,在Assistant的物件中Person會有兩份,

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; // 主修課程
};
void Test()
{
	// 這樣會有二義性無法明確知道訪問的是哪一個
	Assistant a;
	a._name = "peter";
	// 需要顯示指定訪問哪個父類的成員可以解決二義性問題,但是資料冗余問題無法解決
	a.Student::_name = "xxx";
	a.Teacher::_name = "yyy";
}

在這里插入圖片描述
在這里插入圖片描述

虛擬繼承可以解決菱形繼承的二義性和資料冗余的問題,如上面的繼承關系,在Student和Teacher的繼承Person的時候使用虛擬繼承,即可解決問題,需要注意,虛擬繼承不要在其他地方使用,

class Person
{
public:
	string _name; // 姓名
};
class Student :virtual public Person	//加關鍵字virtual
{
protected:
	int _num; //學號
};
class Teacher :virtual  public Person
{
protected:
	int _id; // 職工編號
};
class Assistant : public Student, public Teacher
{
protected:
	string _majorCourse; // 主修課程
};
void Test()
{
	// 這樣會有二義性無法明確知道訪問的是哪一個
	Assistant a;
	a._name = "peter";
	// 需要顯示指定訪問哪個父類的成員可以解決二義性問題,但是資料冗余問題無法解決
	a.Student::_name = "xxx";
	a.Teacher::_name = "yyy";
}

虛擬繼承解決資料冗余和二義性的原理

為了研究虛擬繼承的原理,我們給出了一個簡化的菱形繼承繼承體系,再借助記憶體視窗觀察物件成員的模型,

菱形繼承:

class A {
public:
	int _a;
};

class B :public A{
public:
	int _b;
};

class C :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;
}

菱形繼承可以看到資料的冗余性,_a屬性在兩塊空間都有存盤,

在這里插入圖片描述

菱形虛擬繼承:

class A {
public:
	int _a;
};

class B : virtual public A{
public:
	int _b;
};

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;
}

下圖是菱形虛擬繼承的記憶體物件成員模型:這里可以分析出D物件中A放到了物件組成的最下面,這個A同時也是屬于B、C,那么B、C是如何找到公共的A呢?這里是通過了B和C的兩個指標,指向的一張表,這兩個指標叫虛基表指標,這兩個表叫虛基表,虛基表中存的偏移量,通過偏移量可以找到A,

在這里插入圖片描述

當發生派生類物件轉換為基類物件時,那么基類物件怎么去找屬于自己的那一部分資料呢?

D d;
B b=d;
C c=d;

下圖是上面菱形繼承的原理解釋圖:

在這里插入圖片描述

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/282653.html

標籤:其他

上一篇:初步學習BFS的心得體會

下一篇:藍橋杯單片機第十屆國賽 部分功能決議

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more