關于隱藏、覆蓋(重寫)、重載的理解

定義區分

  • 在派生-對象中:優先考慮隱藏,此時派生類中的覆蓋(重寫)也是隱藏;沒有隱藏的情況下,子類對象才能調用父類重載函數。[此時感覺virtual沒用,]
  • 在派生-指針或者引用中:只用覆蓋(重寫)和重載;
    注:C++ Primmer P550解釋為:D1的fnc并沒有覆蓋(重寫)Base的虛函數fnc…實際上,D1…此時擁有了兩個名為fnc的函數:一個是D1從Base繼承而來的(隱藏的)虛函數fnc;另一個是D1自己定義的接受的接受int參數的非虛函數fnc。

其他有利于理解的說法:如果派生類定義了一個與基類成員函數同名的函數(無論參數列表是否相同),那么派生類中的這個函數將隱藏基類中的所有同名函數(隱藏僅僅指類的對象,對于指向派生類的基類指針仍然可以調用其他虛函數)

下面是我寫的兩個函數示例(后續優化)

/*
* 知識點:隱藏、覆蓋(重寫)、重載
* One:對于隱藏、覆蓋(重寫)
*     在派生-對象中:優先考慮隱藏,此時派生類中的覆蓋(重寫)也是隱藏;沒有隱藏的情況下,子類對象才能調用父類重載函數。[此時感覺virtual沒用,]
*     在派生-指針或者引用中:只用覆蓋(重寫)和重載;
*
*
其他有利于理解的說法
* 如果派生類定義了一個與基類成員函數同名的函數(無論參數列表是否相同),
* 那么派生類中的這個函數將隱藏基類中的所有同名函數(隱藏僅僅指類的對象,
* 對于指向派生類的基類指針仍然可以調用其他虛函數)
*/#include <iostream>
using namespace std;class Base
{
public:Base(int a) : m_v(a) {}virtual void setM() { m_v = 0; }virtual void setM(int a) { m_v = a; }virtual int getM() { return m_v; }
protected:int m_v;
};class Drive : public Base
{
public:Drive() : Base(42) {}void setM() override { m_v = 1000; } // 使用 override 關鍵字明確這是一個重寫的方法
};class DDrive : public Drive
{
public:DDrive() : Drive() {}
};int main()
{Base b(6);cout << "Base: " << b.getM() << endl;  // 輸出 6b.setM();cout << "Base setM() default(0): " << b.getM() << endl;  // 輸出 0,因為調用了 Base 的 setM()b.setM(9);cout << "Base setM(9): " << b.getM() << endl;  // 輸出 9cout << endl;Drive d;cout << "Drive Base default(): " << d.getM() << endl; // 輸出 42,因為 Drive 的構造函數調用了 Base(42)d.setM();cout << "Drive setM() default(0): : " << d.getM() << endl; // 輸出 1000,因為調用了 Drive 的 setM()//d.setM(1001);   // Error:函數調用參數過多;派生類對象對父類進行隱藏//cout << "Drive (1001) : " << d.getM() << endl; // 輸出 1000,因為調用了 Drive 的 setM()// 以下部分展示了多態性Base* pb = &b;cout << "Base: " << pb->getM() << endl;  // 輸出 9pb->setM();cout << "Base: " << pb->getM() << endl;  // 輸出 0,因為 pb 指向 Base 對象,調用了 Base 的 setM()pb->setM(9);cout << "Base: " << pb->getM() << endl;  // 輸出 9Base* pd = &d;cout << "Drive: " << pd->getM() << endl; // 輸出 1000pd->setM();cout << "Drive: " << pd->getM() << endl; // 輸出 1000,因為 pd 指向 Drive 對象,調用了 Drive 的 setM()pd->setM(1001);cout << "Drive: " << pd->getM() << endl; // 輸出 1001,因為調用了 Drive 的 setM(int)// 延申:子類的不恰當隱藏會影響到孫類"!!!對象!!!",但并不影響孫類指針DDrive dd;cout << "Drive Base default(): " << dd.getM() << endl;dd.setM();cout << "Drive setM() default(0): : " << dd.getM() << endl;//dd.setM(1001);    // Error:函數調用參數過多;子類的不恰當隱藏會影響到孫類!!!對象!!!cout << "Drive (1001) : " << dd.getM() << endl;Base* pdd = &dd;cout << "Drive: " << pdd->getM() << endl;pdd->setM();cout << "Drive: " << pdd->getM() << endl;pdd->setM(1001);cout << "Drive: " << pdd->getM() << endl;return 0;
}

還有個更長的示例

#include <iostream>
using namespace std;/*
*一、
*在C++中,重寫(Override)和隱藏(Hiding)是兩個不同的概念,它們在某些情況下可能會產生沖突或混淆,尤其是在涉及繼承時。
但是,這兩個概念本身并不直接沖突,而是需要開發者明確理解和區分它們以避免潛在的問題。- 重寫(Override)
重寫發生在子類中,當子類提供了一個與基類中的虛函數具有相同簽名(即相同的函數名、返回類型、參數列表)的成員函數時。
這允許子類改變從基類繼承的虛函數的行為。重寫是動態綁定的一部分,因此當通過基類指針或引用調用重寫的虛函數時,將調用子類中的版本(如果指針或引用實際上指向子類對象)。- 隱藏(Hiding)
隱藏也發生在子類中,但它通常與名稱沖突相關。當子類提供了一個與基類中的非虛函數具有相同名稱的成員函數時,基類的該函數在子類中將被隱藏。
這意味著在子類的**對象**直接調用該函數時,將調用子類中的版本,而不是基類中的版本。
但是,如果通過基類指針或引用調用該函數(即使該指針或引用實際上指向子類對象),仍然會調用基類中的版本(除非基類中的函數也是虛函數)。*沖突和混淆
- 重寫和隱藏之間的主要混淆在于它們都與函數名和繼承有關,但行為卻截然不同。如果開發者不清楚何時發生重寫、何時發生隱藏,可能會導致意外的行為。
- 此外,如果基類中的函數被設計為虛函數(以支持多態),但子類中的同名函數沒有被聲明為override(在C++11及更高版本中支持),并且基類中的函數簽名在子類中發生了更改(例如參數數量或類型不同),
那么子類中的函數實際上將隱藏基類中的虛函數,而不是重寫它。
這可能導致代碼中的錯誤,因為開發者可能期望實現多態行為,但實際上卻得到了隱藏行為。為了避免這種混淆,建議:
- 在子類中重寫基類的虛函數時,使用override關鍵字(如果編譯器支持)。這將使編譯器在基類中沒有匹配的虛函數時發出錯誤。
- 盡量避免在子類中隱藏基類中的非虛函數,除非這是有意為之。如果必須這樣做,請確保在文檔和注釋中清楚地說明這一點。
- 理解多態、重寫和隱藏的概念,并始終注意在涉及繼承時的函數簽名和訪問級別。*二、如果你遇到d2.doSomething(3.14)不能調用Base類的doSomething(double a)方法的情況,可能有幾個原因:①隱藏基類方法:如果在Derived2或它的直接基類Derived中有任何重載版本的doSomething方法,并且沒有使用using聲明來引入基類的方法,基類的方法可能會被隱藏。
這意味著,即使基類中存在doSomething(double a),如果派生類中定義了其他版本的doSomething(如doSomething(int)或doSomething(char)),
但沒有顯式地引用基類的方法,基類版本的方法在派生類對象上可能無法直接訪問。
②名稱隱藏:在C++中,如果派生類中定義了與基類相同名稱的成員函數,即使參數列表不同,基類中的同名函數也會被隱藏。
這是C++的名稱隱藏規則,不同于重載。
③訪問控制:如果Base類的doSomething方法是protected或private,則不能在Derived2類的對象上直接調用它(盡管這種情況不太可能,因為你提到了virtual,這通常意味著方法應該是public的)。另一方面,dp2->doSomething(3.14);可以工作,可能是因為dp2是一個指向Derived2的指針,但是被當做Base類的指針來使用。
當你通過基類指針調用一個virtual函數時,C++的多態性確保調用的是指針實際指向的對象的最具體的實現(即動態綁定)。
如果Derived2沒有重載doSomething(double a),則調用會回退到Base類的實現。如果d2.doSomething(3.14)不工作,而dp2->doSomething(3.14);工作,最可能的原因是名稱隱藏。
在派生類中定義新的doSomething函數時,如果沒有正確地使用using聲明來引入基類的函數,基類的同名函數會被隱藏
*/class Base {
public:virtual void doSomething(int a) {// 基類的doSomething(int)方法  std::cout << "Base::doSomething(int) called with " << a << std::endl;}virtual void doSomething(char a) {// 基類的doSomething(double)重載方法  std::cout << "Base::doSomething(char) called with " << a << std::endl;}virtual void doSomething(int a, int b, int c) {// 基類的doSomething(double)重載方法  std::cout << "Base::doSomething(int a,int b, int c) called with a:" << a << ", b:" << b << ", c:" << c << std::endl;}void doSomething(int a, int b, int c, int d) {// 基類的doSomething(double)重載方法  std::cout << "Base::doSomething(int a, int b, int c, int d) called with a:" << a << ", b:" << b << ", c:" << c << ", d:" << d << std::endl;}void coutName() {// 基類的coutName重載方法  std::cout << "Base::coutName" << std::endl;}
};class Derived1 : public Base {
public://using Base::doSomething;void doSomething(int a) {// 派生類重寫了基類的doSomething(int)方法  std::cout << "Derived1::doSomething(int) called with " << a << std::endl;}//using Base::doSomething;void doSomething(char c) {// 派生類重寫了基類的doSomething(char c)方法  std::cout << "Derived1::doSomething(char) called with " << c << std::endl;}
};class Derived2 : public Base {
public://using Base::doSomething;void doSomething(int a) {// 派生類重寫了基類的doSomething(int)方法  std::cout << "Derived2::doSomething(int) called with " << a << std::endl;}virtual void doSomething(int a, int b, int c, int d) {// 派生類重寫了基類的doSomething(int a, int b, int c, int d)方法  std::cout << "Derived2::doSomething(double) called with a:" << a << ", b:" << b << ", c:" << c << ", d:" << d << std::endl;}
};class Derived3 : public Base {
public://using Base::doSomething;void doSomething(int a) {// 派生類重寫了基類的doSomething(int)方法  std::cout << "Derived3::doSomething(int) called with " << a << std::endl;}//using Base::doSomething;void doSomething(int x, int y) {// 派生類重載了doSomething(int x, int y)方法std::cout << "Derived3::doSomething(int x, int y) called with x:" << x << ",y:" << y << std::endl;}
};class Derived11 : public Derived1 {
public://using Base::doSomething;void doSomething(int a) {// 派生類重寫了基類的doSomething(int)方法  std::cout << "Derived11::doSomething(int) called with " << a << std::endl;}
};class Derived21 : public Derived2 {
public://using Base::doSomething;void doSomething(int a) {// 派生類重寫了基類的doSomething(int)方法  std::cout << "Derived21::doSomething(int) called with " << a << std::endl;}
};class Derived31 : public Derived3 {
public://using Base::doSomething;void doSomething(int a) {// 派生類重寫了基類的doSomething(int)方法  std::cout << "Derived31::doSomething(int) called with " << a << std::endl;}
};int main() {cout << "************************************實例化對象開始表演******************************************************" << endl;Base b1;b1.doSomething(42);//b1.doSomething(3.14);      //  !!!編譯報錯提示"有多個重載函數 實例與參數列表相同,26和31行",因為3.14不知道轉換為int,還是charb1.doSomething('c');b1.doSomething(1, 2, 3);b1.doSomething(1, 2, 3, 4);b1.coutName();cout << endl << endl;Derived1 d1;d1.doSomething(42);            // 調用Derived1的doSomething(int)  //d1.doSomething(3.14);          // !!!編譯報錯提示"有多個重載函數 實例與參數列表相同,56和62行",因為3.14不知道轉換為int,還是chard1.doSomething('c');           // !!!'c'轉化內int//d1.doSomething(1, 2, 3);     // !!!報錯提示"沒有與參數列表匹配的 重載函數Derived1::doSomething, 參數類型為(int, int, int)"//d1.doSomething(1, 2, 3, 4);  // !!!報錯提示"沒有與參數列表匹配的 重載函數Derived1::doSomething, 參數類型為(int, int, int, int)"d1.coutName();                 // 調用基類的doSomething(double),因為派生類沒有重寫它  cout << endl << endl;Derived2 d2;d2.doSomething(42);    // 調用Derived2的doSomething(int)  d2.doSomething(3.14);  // 3.14轉換為int,調用相同d2.doSomething('c');   // 'c'轉化內int//d2.doSomething(1, 2, 3);//!!!報錯提示"沒有與參數列表匹配的 重載函數Derived2::doSomething, 參數類型為(int, int, int)"d2.doSomething(1, 2, 3, 4); //!!!這是Derived2自身的函數,與Base沒有關系d2.coutName();         // 調用基類的doSomething(double),因為派生類沒有重寫它 // !!!子類Derived3::doSomething(int x, int y),是否對父類方法進行隱藏。也就是說d3是否擁有doSomething(double a)???cout << endl << endl;Derived3 d3;d3.doSomething(42);    // 調用Derived2的doSomething(int)  d3.doSomething(3.14);  // 3.14轉換為int,調用相同d3.doSomething('c');   // 'c'轉化內int//d3.doSomething(1, 2, 3);     // !!!報錯提示"沒有與參數列表匹配的 重載函數Derived3::doSomething, 參數類型為(int, int, int)"//d3.doSomething(1, 2, 3, 4);  // !!!報錯提示"沒有與參數列表匹配的 重載函數Derived3::doSomething, 參數類型為(int, int, int, int)"d3.doSomething(1, 2);   //!!!這是Derived3自身的函數,與Base沒有關系d3.coutName();         // 調用基類的doSomething(double),因為派生類沒有重寫它 cout << endl << endl;cout << "******************創建Derived1、Derived2、Derived3單獨的指針(感覺類實例化對象用法一致)*********************************************" << endl;Derived1* opd1 = new Derived1;opd1->doSomething(42);    // 調用Derived1::doSomething(int)  opd1->doSomething('c');   // 調用Derived1::doSomething(char)//opd1->doSomething(1, 2, 3); // !!!報錯提示"沒有與參數列表匹配的 重載函數Derived1::doSomething, 參數類型為(int, int, int)"//opd1->doSomething(1, 2, 3, 4);// !!!報錯提示"沒有與參數列表匹配的 重載函數Derived1::doSomething, 參數類型為(int, int, int, int)"opd1->coutName();cout << endl << endl;Derived2* opd2 = new Derived2;opd2->doSomething(42);    // 調用Derived2的doSomething(int)  opd2->doSomething('c');   // 調用Base::doSomething(char)//opd2->doSomething(1, 2, 3);//!!!報錯提示"沒有與參數列表匹配的 重載函數Derived2::doSomething, 參數類型為(int, int, int)"opd2->doSomething(1, 2, 3, 4); // !!!這是Derived2自身的函數,與Base沒有關系opd2->coutName();cout << endl << endl;Derived3* opd3 = new Derived3;opd3->doSomething(42);    // 調用Derived2的doSomething(int)  opd3->doSomething('c');   // 'c'轉化內int//opd3->doSomething(1, 2, 3);// !!!報錯提示"沒有與參數列表匹配的 重載函數Derived3::doSomething, 參數類型為(int, int, int)"//opd3->doSomething(1, 2, 3, 4); // !!!報錯提示"沒有與參數列表匹配的 重載函數Derived3::doSomething, 參數類型為(int, int, int, int)"opd3->doSomething(1, 2);   // !!!報錯提示"沒有與參數列表匹配的 重載函數Base::doSomething, 參數類型為(int, int)"opd3->coutName();cout << endl << endl;cout << "******************創建基類指針分別指向Derived1、Derived2、Derived3(virtual在派生類中多態應用)**************************************" << endl;Base* pd1 = new Derived1;pd1->doSomething(42);    // 調用Derived1::doSomething(int)  pd1->doSomething('c');   // 調用Derived1::doSomething(char)pd1->doSomething(1, 2, 3);// 調用Base::doSomething(int, int, int)pd1->doSomething(1, 2, 3, 4);// 調用Base::doSomething(int, int, int, int)pd1->coutName();cout << endl << endl;Base* pd2 = new Derived2;pd2->doSomething(42);    // 調用Derived2的doSomething(int)  pd2->doSomething('c');   // 調用Base::doSomething(char)pd2->doSomething(1, 2, 3);// 調用Base::doSomething(int, int, int)pd2->doSomething(1, 2, 3, 4); // !!! 這里調用基類Base::doSomething(int, int, int, int),因為不是虛函數,子類Derived2沒有對其重寫pd2->coutName();cout << endl << endl;Base* pd3 = new Derived3;pd3->doSomething(42);    // 調用Derived2的doSomething(int)  pd3->doSomething('c');   // 'c'轉化內intpd3->doSomething(1, 2, 3);// 調用Base::doSomething(int, int, int)pd3->doSomething(1, 2, 3, 4);// 調用Base::doSomething(int, int, int, int)//pd3->doSomething(1, 2);   // !!!報錯提示"沒有與參數列表匹配的 重載函數Base::doSomething, 參數類型為(int, int)"pd3->coutName();cout << endl << endl;cout << "******************創建Derived11、Derived21、Derived31單獨的指針(感覺類實例化對象用法一致)*********************************************" << endl;Derived11* opd11 = new Derived11;opd11->doSomething(42);    // 調用Derived11::doSomething(int)  opd11->doSomething('c');  // 'c'轉化內int//opd11->doSomething(1, 2, 3); // !!!報錯提示"參數太多",我感覺跟原來哪個意思一樣("沒有與參數列表匹配的 重載函數Derived11::doSomething, 參數類型為(int, int, int)")//opd11->doSomething(1, 2, 3, 4);// !!!報錯提示"參數太多"opd11->coutName();cout << endl << endl;Derived21* opd21 = new Derived21;opd21->doSomething(42);    // 調用Derived21的doSomething(int)  opd21->doSomething('c');   // 'c'轉化內int//opd21->doSomething(1, 2, 3);// !!!報錯提示"參數太多"//opd21->doSomething(1, 2, 3, 4); // !!!報錯提示"參數太多"opd21->coutName();cout << endl << endl;Derived31* opd31 = new Derived31;opd31->doSomething(42);    // 調用Derived2的doSomething(int)  opd31->doSomething('c');   // 'c'轉化內int//opd31->doSomething(1, 2, 3);;// !!!報錯提示"參數太多"//opd31->doSomething(1, 2, 3, 4);;// !!!報錯提示"參數太多"//opd31->doSomething(1, 2); ;// !!!報錯提示"參數太多"opd31->coutName();cout << endl << endl;cout << "******************創建基類指針分別指向Derived11、Derived21、Derived31(virtual在派生類中多態應用)**************************************" << endl;Base *pd11 = new Derived11;pd11->doSomething(42);    // 調用Derived1::doSomething(int)  pd11->doSomething('c');   // 調用Derived1::doSomething(char)pd11->doSomething(1, 2, 3);// 調用Base::doSomething(int, int, int)pd11->doSomething(1, 2, 3, 4);// 調用Base::doSomething(int, int, int, int)pd11->coutName();cout << endl << endl;Base *pd21 = new Derived21;pd21->doSomething(42);    // 調用Derived2的doSomething(int)  pd21->doSomething('c');   // 調用Base::doSomething(char)pd21->doSomething(1, 2, 3);// 調用Base::doSomething(int, int, int)pd21->doSomething(1, 2, 3, 4); // !!! 這里調用基類Base::doSomething(int, int, int, int),因為不是虛函數,子類Derived2沒有對其重寫pd21->coutName();cout << endl << endl;Base* pd31 = new Derived31;pd31->doSomething(42);    // 調用Derived2的doSomething(int)  pd31->doSomething('c');   // 'c'轉化內intpd31->doSomething(1, 2, 3);// !!!報錯提示"參數太多"pd31->doSomething(1, 2, 3, 4);// !!!報錯提示"參數太多"//pd31->doSomething(1, 2);  // !!!報錯提示"參數太多"pd31->coutName();cout << endl << endl;return 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/42421.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/42421.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/42421.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

《Programming from the Ground Up》閱讀筆記:p19-p48

《Programming from the Ground Up》學習第2天&#xff0c;p19-p48總結&#xff0c;總計30頁。 一、技術總結 1.object file p20, An object file is code that is in the machine’s language, but has not been completely put together。 之前在很多地方都看到object fi…

高階K8S面試題你會幾個?

前言 K8S架構、公有云、持久化存儲、HELM、CICD、負載均衡、監控告警、可觀察性、服務治理、架構探索。。。 Q1&#xff1a;如何調試 Kubernetes 集群中的網絡連接問題&#xff0c;比如 Pod 間通信失敗的情況&#xff1f; 狀態檢查&#xff1a;使用 kubectl get pods 和 kube…

MySQL-17-mysql alter 語句如何實現?如何合并為一個

拓展閱讀 MySQL 00 View MySQL 01 Ruler mysql 日常開發規范 MySQL 02 truncate table 與 delete 清空表的區別和坑 MySQL 03 Expression 1 of ORDER BY clause is not in SELECT list,references column MySQL 04 EMOJI 表情與 UTF8MB4 的故事 MySQL 05 MySQL入門教程&a…

Git使用中遇到的問題(隨時更新)

問題1.先創建本地庫&#xff0c;后拉取遠程倉庫時上傳失敗的問題怎么解決&#xff1f; 操作主要步驟&#xff1a; step1 設置遠程倉庫地址: $ git remote add origin gitgitee.com:yourAccount/reponamexxx.git step2 推送到遠程倉庫: $ git push -u origin "master&qu…

線程池理解及7個參數

定義理解 線程池其實是一種池化的技術實現&#xff0c;池化技術的核心思想就是實現資源的復用&#xff0c;避免資源的重復創建和銷毀帶來的性能開銷。線程池可以管理一堆線程&#xff0c;讓線程執行完任務之后不進行銷毀&#xff0c;而是繼續去處理其它線程已經提交的任務。 …

GStreamer學習5----probe數據探測

參考資料&#xff1a; gstreamer中如何使用probe&#xff08;探針&#xff09;獲取幀數據_gstreamer 視頻編碼時獲取視頻關鍵幀信息-CSDN博客 Gstreamer中可以使用AppSink作為一個分支來查看管線中的數據&#xff0c;還可以使用probe去處理。 在GStreamer中&#xff0c;probe…

LayerNorm Plugin的使用與說明

目錄 前言0. 簡述1. Layernorm Plugin的使用1.1 源碼下載1.2 模型下載和修改1.3 環境配置1.4 編譯1.4 engine生成和執行(trtexec)1.5 enging生成和執行(C API) 2. 補充說明2.1 RTMO顯存占用問題2.2 插件找不到的說明2.3 LayerNorm plugin封裝的嘗試2.4 layerNorm plugin核函數實…

拉曼光譜入門:3.拉曼光譜的特征參數與定量定性分析策略

1.特征參數 1.1 退偏振率 退偏振率&#xff08;p&#xff09;是一個衡量拉曼散射光偏振狀態的參數&#xff0c;它描述了拉曼散射光的偏振方向與入射光偏振方向之間的關系。退偏振率定義為垂直偏振方向的拉曼散射強度與平行偏振方向的拉曼散射強度之比。退偏振率&#xff08;p&…

禁用windows的語音識別快捷鍵win+ctrl+s

win11組合鍵winctrls會彈出語音識別提示&#xff0c;即使到設置里禁用了語音識別也沒用 解決辦法&#xff1a;安裝PowerToys&#xff0c;通過“鍵盤管理器”-“重新映射快捷鍵”禁用 PowerToys是微軟自己的工具&#xff0c;不用擔心安全問題&#xff0c;下載地址&#xff1a;h…

系統設計題-簡易數據庫系統

一、設計一個簡易數據庫系統&#xff0c;包含create&#xff0c;insert&#xff0c;select三個指令。 create(int tableId,int colNum,String key)&#xff1a;創建表&#xff0c;其id為tableId&#xff0c;如果該表已存在&#xff0c;則不做任何處理。colNum為表中列的數量&a…

洛谷 P3008 [USACO11JAN] Roads and Planes G

題意 有一張 n n n 點 ( m 1 m 2 ) (m_1m_2) (m1?m2?) 邊的無向圖&#xff0c;其中 m 1 m_1 m1? 條為無向邊&#xff0c;另外 m 2 m_2 m2? 條為有向邊&#xff0c; 無向邊的邊權可以為負。求 s s s 到其他每個點的最短路。 思路 使用 SPFA 會 T 掉一兩個點&#x…

第10章:網絡與信息安全

目錄 第10章&#xff1a;網絡與信息安全 網絡概述 計算機網絡概念 計算機網絡的分類 網絡的拓撲結構 ISO/OSI網絡體系結構 網絡互聯硬件 物理層互聯設備 數據鏈路層互聯設備 網絡層互聯設備 應用層互聯設備 網絡的協議與標準 網絡標準 TCP/IP協議族 網絡接口層協…

GCC擴展功能、函數,預處理命令

文章目錄 前言一、GCC C語言擴展聲明函數屬性變量屬性內斂匯編與原子操作相關的內建函數內存模型感知原子操作的內置函數使用溢出檢查執行算術的內置函數 - xxx 二、GCC C語言擴展interface和 pragmasTemplate 二、預處理過程及其指令預處理過程1. 字符集轉換2. Initial proces…

實現基于Spring Cloud的事件驅動微服務

實現基于Spring Cloud的事件驅動微服務 大家好&#xff0c;我是免費搭建查券返利機器人省錢賺傭金就用微賺淘客系統3.0的小編&#xff0c;也是冬天不穿秋褲&#xff0c;天冷也要風度的程序猿&#xff01; 事件驅動架構在現代微服務架構中越來越受歡迎&#xff0c;它通過事件的…

【JAVA多線程】線程池概論

目錄 1.概述 2.ThreadPoolExector 2.1.參數 2.2.新任務提交流程 2.3.拒絕策略 2.4.代碼示例 1.概述 線程池的核心&#xff1a; 線程池的實現原理是個標準的生產消費者模型&#xff0c;調用方不停向線程池中寫數據&#xff0c;線程池中的線程組不停從隊列中取任務。 實現…

最新版Python安裝教程

一、安裝Python 1.下載Python 訪問Python官網&#xff1a; https:/www.oython.orgl 點擊downloads按鈕&#xff0c;在下拉框中選擇系統類型(windows/Mac OS./Linux等) 選擇下載最新穩定版本的Python 以下內容以演示安裝Windows操作系統64位的python 左邊是穩定發布版本Stabl…

python網絡編程-TCP/IP

鏈路層 幀組成&#xff08;按順序&#xff09;&#xff1a; 目標MAC&#xff1a;6B 源MAC&#xff1a;6B 類型&#xff1a;2B 數據&#xff1a;46B-1500B CRC&#xff1a;4B 其中&#xff0c;源MAC為主機網卡地址&#xff0c;類型為來源網絡層的數據類型&#xff0c;ipv…

Self-Instruct構造Prompt的例子

人工構造一批Prompt做種子。&#xff08;Starting with a small seed set of human-written tasks&#xff09;每次把一些種子后來生成的Prompt&#xff0c;放到Input里做few-shot examples&#xff0c;用LLM生成更多的Prompt&#xff1b;&#xff08;Using the LLM to generat…

PyTorch學習之torch.transpose函數

PyTorch學習之torch.transpose函數 一、簡介 torch.transpose 函數我們用于交換張量的維度。 二、語法 torch.transpose 函數用于交換給定張量的兩個維度&#xff0c;其語法如下&#xff1a; torch.transpose(input, dim0, dim1)三、參數 input&#xff1a;待交換維度的張…

kotlin 基礎

文章目錄 1、安裝 Java 和 Kotlin 環境2、程序代碼基本結構3、變量的聲明與使用4、數據類型5、數字類型的運算1&#xff09;布爾類型2&#xff09;字符類型3&#xff09;字符串類型 6、 選擇結構1)&#xff08;if - else&#xff09;2&#xff09; 選擇結構&#xff08;when&am…