主頁 > 軟體設計 > C++物件模型總結

C++物件模型總結

2021-02-01 13:05:10 軟體設計

C++物件模型

物件

物件模型分類

在C++中,成員資料(class data member)有兩種:static和nonstatic,成員函式(class member function)有三種:static、nonstatic和virtual,

  • 簡單物件模型

    class Point
    {
    public:
    Point(float xval);
    virtual ~Point();
    float x() const;
    static int PointCount();
    protected:
    virtual ostream& print(ostream& os) const;
    float _x;
    static int _point_count;
    };

  • 表格驅動模型

  • c++物件模型(目前采用的物件模型)

類物件所占用的空間

  • 一個空類占一個位元組

    class A
    {
    public:

    };
    int main()
    {
    A obj;
    cout << sizeof(obj) << endl; //1
    cout << sizeof(A) << endl;//1
    }

  • 普通成員函式和靜態成員函式不計算在sizeof內

    一:
    class A
    {
    public:
    void fun(){}//成員函式,靜態成員函式也不占用記憶體空間
    };
    int main()
    {
    A obj;
    cout << sizeof(obj) << endl;//1
    cout << sizeof(A) << endl;//1
    }

    二:
    class A
    {
    public:
    void fun(){ int a; }//成員函式

    };
    int main()
    {
    A obj;
    cout << sizeof(obj) << endl;//1
    cout << sizeof(A) << endl;//1
    }

  • 靜態成員變數不計算在sizeof內

    class A
    {
    public:
    static int a;
    static int b;
    };
    int main()
    {
    A obj;
    cout << sizeof(obj) << endl;//1
    cout << sizeof(A) << endl;//1
    }

    結論:靜態成員變數跟著類走,不占用物件記憶體空間,

  • 虛函式不計算在物件的sizeof內,但是會存在一個虛函式表指標

    class A
    {
    public:

       virtual void fun1(){ }
       virtual void fun2(){ }
    

    };
    int main()
    {
    A obj;
    cout << sizeof(obj) << endl;//4
    cout << sizeof(A) << endl;//4
    }
    結論:不管虛函式有幾個,都是占4個位元組,
    虛函式表:vtbl
    虛函式表:跟著類走,用來保存指向類里面每個虛函式的指標,即如果類里面有一個虛函式,那保存的指標就有一個,如果有兩個虛函式,那虛函式表里就就保存有兩個指標,

    針對于上面的結果進行分析,為什么是占用4個位元組呢?
    答:這4個位元組是一個指標(vptr),這個指標用來指向虛函式表,
    這個指標的值,系統會在適當的時機,比如呼叫建構式時,給這個指標賦值,也就是虛函式表的首地址,
    結論:虛函式不計算在類物件的sizeof里,但是會額外增加一個虛函式表指標
    另外,虛解構式也是占用4個位元組,
    需要說明的是:為什么普通成員函式不需要搞虛函式表,而虛函式例外呢?
    因為虛函式的多型性問題,所以虛函式的處理方式與普通的成員函式不一樣,

  • 位元組對齊問題

    位元組對齊總的來說是為了提高訪問速度,

    如果類里有的成員變數是指標,例如,int *p,char *str等等,就占用4個位元組,,當然Linux平臺下可能是8位元組,

this指標調整問題(出現在多重繼承中,呼叫哪個子類的成員函式,這個this指標就會被編譯器自動調整到物件記憶體布局中對應改子類物件的起始地址那去

范例一:
class A
{
public:
A()
{
printf(“A():%p\n”, this);
}
void funA()
{
printf(“funA():%p\n”, this);
}
public:
int a;
};
class B
{
public:
B()
{
printf(“B():%p\n”, this);
}
void funB()
{
printf(“funB():%p\n”, this);
}
public:
int b;
};
class C :public A, public B //繼承的順序和類C的記憶體空間布局有關
{
public:
C()
{
printf(“C():%p\n”, this);
}
void funC()
{
printf(“funC():%p\n”, this);
}
public:
int c;
};
int main()
{
cout << sizeof(A) << endl;
cout << sizeof(B) << endl;
cout << sizeof? << endl;
C obj;
obj.funA();
obj.funB();
obj.funC();
}

結論:如果派生類只繼承一個基類,那么這個基類的地址和派生類的地址相同,
如果一個類,同時繼承多個基類,那么這個子類的物件和它繼承順序的第一個基類的地址相同,

范例二:
class A
{
public:

   A()
   {
          printf("A():%p\n", this);
   }
   void funA()
   {
          printf("A::funA():%p\n", this);
   }

public:
int a;
};
class B
{
public:
B()
{
printf(“B():%p\n”, this);
}
void funB()
{
printf(“B::funB():%p\n”, this);
}
public:
int b;
};
class C :public A, public B
{
public:
C()
{
printf(“C():%p\n”, this);
}
void funB() //覆寫掉類B中的funb函式,所以呼叫該函式時,使用的this指標就會調整,即用類C的this指標去呼叫該函式,
{
printf(“C::funB():%p\n”, this);
}
void funC()
{
printf(“C::funC():%p\n”, this);
}
public:
int c;
};
int main()
{
cout << sizeof(A) << endl;
cout << sizeof(B) << endl;
cout << sizeof? << endl;
C obj;
obj.funA();
obj.funB();
obj.funC();
}

總結:該案列只有一些簡單的成員函式,無虛函式,,所以分析起來也較簡單,
這種情況的話,一般時出現在多重繼承(繼承多個父類)中,,后面的話,,呼叫那個子類或者父類的成員函式,,就用誰的this指標去呼叫,
比如說,,這里有3個類,,A和C的this指標是相同的(和繼承順序有關),所以呼叫A和C的成員函式的this指標相同,,呼叫B的成員函式,就用B的this指標去呼叫,
上面,C類覆寫了B里的一個成員函式,所以再呼叫這個成員函式的話,呼叫這個函式的話就變成呼叫C里的這個函式了,也就是用C的this指標去呼叫,

編譯器合成默認建構式的5種情況

  • 如果一個類沒有任何建構式,但包含一個型別別的成員變數,而這個型別別的成員變數有一個默認建構式

    class A
    {
    public:
    A()
    {
    cout << “aaaaa” << endl;
    }
    };

    class C
    {
    public:
    int c;
    A a;
    };
    int main()
    {
    C c;//會呼叫A()
    }
    分析:為什么會呼叫A()呢?其實是編譯器為類C合成了一個默認的建構式,而這個默認建構式又去呼叫A(),來初始化a,所以會呼叫A()

  • 父類帶有默認建構式,子類沒有任何建構式

    class A
    {
    public:
    A()
    {
    cout << “aaaaa” << endl;
    }
    };
    class B:public A
    {
    public:

    };
    int main()
    {
    B b;
    }

    父類有一個默認建構式,而子類沒有建構式時,編譯器會為子類合成一個默認建構式,從而讓這個合成的默認建構式去呼叫父類中的建構式,

  • 一個類有虛函式,但是該類沒有任何建構式

    note:有虛函式,就會存在虛函式表,所以編譯器會合成一個默認建構式,這個默認建構式的目的是將虛函式表首地址賦給虛函式表指標,

    class A
    {
    public:

       virtual void fun()
       {
              cout << "aaaaa" << endl;
       }
    

    };

    A a;//只是這里不會去呼叫該虛函式,因為編譯器安插的代碼中沒這么干,

  • 一個類帶有虛基類(給虛基類表賦值以及呼叫父類的建構式)

    虛基類(虛繼承)只會出現在三層結構中:
    class Grand
    {
    public:
    int a;
    };
    class A:virtual public Grand//虛繼承
    {
    public:

    };
    class A2 :virtual public Grand//虛繼承
    {
    public:
    };
    class C :public A, public A2
    {
    public:
    };
    int main()
    {
    C c;
    }

  • 定義成員變數時賦初值(c++11)

    class A
    {
    public:
    int a =10;
    };

編譯器合成拷貝建構式的4種情況

拷貝建構式語意:
傳統上,大家認為:如果我們沒有定義一個自己的拷貝建構式,編譯器會幫助我們合成 一個拷貝建構式,
但,這個合成的拷貝建構式,也是在 必要的時候才會被編譯器合成出來, 所以 “必要的時候”;是指什么時候?
那編譯器在什么情況下會幫助我們合成出拷貝建構式來呢?那這個編譯器合成出來的拷貝建構式又要干什么事情呢?
(1)如果一個類A沒有拷貝建構式,但是含有一個型別別CTB的成員變數m_ctb,該型別CTB含有拷貝建構式,那么當代碼中有涉及到類A的拷貝構造時,編譯器就會為類A合成一個拷貝建構式,
編譯器合成的拷貝建構式往往都是干一些特殊的事情,如果只是一些類成員變數值的拷貝這些事,編譯器是不用專門合成出拷貝建構式來干的,編譯器內部就干了;
(2)如果一個類CTBSon沒有拷貝建構式,但是它有一個父類CTB,父類有拷貝建構式,
當代碼中有涉及到類CTBSon的拷貝構造時,編譯器會為CTBSon合成一個拷貝建構式 ,呼叫父類的拷貝建構式,
(3)如果一個類CTBSon沒有拷貝建構式,但是該類宣告了或者繼承了虛函式,
當代碼中有涉及到類CTBSon的拷貝構造時,編譯器會為CTBSon合成一個拷貝建構式 ,往這個拷貝建構式里插入陳述句:
(4)如果 一個類沒有拷貝建構式, 但是該類含有虛基類
當代碼中有涉及到類的拷貝構造時,編譯器會為該類合成一個拷貝建構式;
(5)(6)其他編譯器合成拷貝建構式的情形留給大家探索,

  • 一個類A沒有建構式,但是含有一個型別別B的成員變數m_b,該型別B含有拷貝建構式,那么當涉及到類A拷貝構造時,編譯器會為類A合成一個拷貝建構式,

    class B
    {
    public:
    B(const B&)
    {
    cout << “B()的拷貝建構式執行了” << endl;
    }
    class A
    {
    public:
    B m_b;
    };

    A a1;
    A a2 =a1;//實際累A的拷貝構造時才會合成

  • 一個類A沒有拷貝建構式,但是它有一個父類,父類有拷貝建構式,當代碼涉及到類A的拷貝構造時,編譯器會類A合成一個拷貝建構式,

    class B
    {
    public:
    B(const B&)
    {
    cout << “B()的拷貝建構式執行了” << endl;
    }
    };
    class A:public B
    {
    public:
    };

    A a1;
    A a2 =a1;//實際累A的拷貝構造時才會合成

  • 一個類A沒有拷貝建構式時,但是該類宣告了或者繼承了虛函式,當代碼中涉及到類A的拷貝構造時,編譯器會為類A合成一個拷貝建構式,(給虛函式表指標值)

    class A
    {
    public:
    virtual void mvirfunc() {}
    };
    A a1;
    A a2 = a1;
    合成的原因是,要把a1這個物件的,虛函式表首地址賦值給虛函式表指標,這個動作,,拷貝給a2,

  • 如果一個類沒有拷貝建構式,但是該類含有虛基類時,當代碼涉及到類的拷貝構造時,編譯器會為該類合成一個拷貝建構式(涉及虛基類表話題)

    虛基類主要解決在多重繼承時,基類可能被多次繼承,虛基類主要提供一個基類給派生類,
    #include
    using namespace std;
    class B0// 宣告為基類B0
    {
    int nv;//默認為私有成員
    public://外部介面
    B0(int n){ nv = n; cout << “Member of B0” << endl; }//B0類的建構式
    void fun(){ cout << “fun of B0” << endl; }
    };
    class B1 :virtual public B0
    {
    int nv1;
    public:
    B1(int a) :B0(a){ cout << “Member of B1” << endl; }
    };
    class B2 :virtual public B0
    {
    int nv2;
    public:
    B2(int a) :B0(a){ cout << “Member of B2” << endl; }
    };
    class D1 :public B1, public B2
    {
    int nvd;
    public:
    D1(int a) :B0(a), B1(a), B2(a){ cout << “Member of D1” << endl; }// 此行的含義,參考下邊的 “使用注意5”
    void fund(){ cout << “fun of D1” << endl; }
    };
    int main(void)
    {
    D1 d1(1);
    d1.fund();
    d1.fun();
    return 0;
    }

拷貝建構式的深淺拷貝問題(同一塊記憶體會釋放兩次的情形)

前言:和默認建構式類似,在某些情況下,我們只能自己定義自己的拷貝建構式,而不能使用系統提供的,因為在某些情況下使用系統提供的拷貝建構式會帶來一定的影響,例如深淺拷貝,
例一:
class Student
{
public:
int m_age;
int *m_heigh;
public:
Student(int heigh, int age);
~Student();
};

Student::Student(int heigh,int age)
{
m_age = age;

m_heigh = new int;//申請記憶體空間
*m_heigh = heigh;//往申請的記憶體空間里寫值

}
Student::~Student()
{
if (m_heigh != nullptr)
{
delete m_heigh;//在堆上申請的記憶體需要手動釋放
m_heigh = nullptr;
}

}

Student s1(10,20);
Student s2 = s1;//由于沒有自己定義拷貝建構式,會造成程式有錯,

當一個類中有指標類的成員時,而我們自己是使用的系統給我們提供的拷貝建構式,在進行了類似于Student s2 = s1
這種類之間的拷貝動作的時候就會造成程式的錯誤了,為什么?

原因在于指標之間的賦值,是把指標指向了一個共同的記憶體地址,所以在進行析構的時候,這個共同的記憶體地址就會析構兩次,所以就造成了系統的crash,這就是淺拷貝,

例二:
那么什么是深拷貝呢?利用自己定義的拷貝建構式就可以解決這個問題,這樣一來,s1和s2的指標都會指向不同的記憶體地址,當然他們各自的記憶體地址當中的值是一樣的,要達到這樣的目的,就是我們說的深拷貝,

class Student
{
public:
int m_age;
int *m_heigh;
public:
Student(int heigh, int age);
~Student();
Student(const Student &s);//拷貝建構式,const防止物件被改變
};

Student::Student(int heigh,int age)
{
m_age = age;

m_heigh = new int;
*m_heigh = heigh;

}
Student::~Student()
{
if (m_heigh != nullptr)
{
delete m_heigh;
m_heigh = nullptr;
}

}
//拷貝建構式里,當發生拷貝時,重新申請了一塊記憶體,這樣就避免了同一塊記憶體地址被釋放兩次,
Student::Student(const Student &s)
{
m_age = s.m_age;

m_heigh = new int;
*m_heigh = *(s.m_heigh);

}

Student s1(10,20);
Student s2 = s1;

cout << s1.m_age << endl;
cout << *(s1.m_heigh) << endl;

cout << s2.m_age << endl;
cout << *(s2.m_heigh) << endl;

移動建構式語意學

程式轉化語意(我們寫的代碼,編譯器會對代碼進行拆分,拆分成編譯器更容易理解和實作的代碼)

  • 定義時初始化

    例如:

    X X0;
    //以下都屬于定義時初始化
    X X1 = X0;
    X X2 = (X0);
    X X3 (X0);

    對于X X3 = X0;

    編譯器如何決議這行代碼?

    編譯器會對這行代碼進行拆分,拆分成以下兩行代碼,
    X X3_3; //在編譯器看來,這當然不會呼叫默認建構式,
    X3_3.X::X(X0);

  • 引數的初始化

  • 函式回傳值

程式的優化

成員初始化串列

https://blog.csdn.net/qq_38158479/article/details/106888318

  • 何時必須使用成員初始化串列

    • 類中含有參考型別的成員
    • 類中含有const型別成員
    • 一個類繼承于另一個類,并且繼承的這個類中有建構式,且建構式帶有引數時
    • 一個類,含有一個型別別成員,并且這個型別別成員有建構式(帶參的)
  • 使用初始化串列的優勢(對于類中含有型別別成員,可以減少一些建構式或者賦值運算子的呼叫以提高程式運行效率)

  • 初始化串列細節探究

    • 初始化串列中的代碼可以看作是被編譯器安插在建構式中的
    • 初始化串列中的代碼是在建構式的函式體之前被執行的
    • 初始化串列成員變數的初始化順序看的是變數在類中定義的順序,而不是看在初始化串列中出現的順序

虛函式

虛函式表指標位置(物件模型的開頭)

單繼承情況下父類和子類虛函式表指標和虛函式表分析

  • 子類中有覆寫父類虛函式時情況分析
  • 子類中沒有覆寫父類虛函式時情況分析

多繼承情況下父類和子類虛函式表指標和虛函式表分析

  • 子類中有覆寫父類或者多個父類虛函式時情況分析
  • 子類中沒有覆寫父類虛函式時情況分析

分析虛函式表的工具與vptr,vtbl創建時機

  • 輔助工具(查看虛函式表指標專用工具)
  • vptr與vtbl都是在編譯期間創建起來的,而給vptr賦值是在運行期間,即,生成物件時,會呼叫建構式進行賦值,

單純的類不純時引發的虛函式呼叫問題(memset和memcpy問題)

  • 單純的類:只有一些簡單的成員變數
  • 不純的類:指類中有一些隱藏的變數,例如虛函式表指標(有虛函式時存在),虛基類表指標
  • 涉及靜態聯編和動態聯編概念

資料語意學

資料成員系結時機

  • 成員函式函式體的決議時機
  • 成員函式引數型別的確定時機

行程記憶體空間布局

資料成員的存取

  • 靜態成員變數的存取
  • 非靜態成員變數的存取

資料成員的布局

  • 單一繼承關系下的資料成員布局(父類和子類都不帶虛函式)–父類和子類的記憶體布局
  • 單一繼承關系下,父類和子類都帶虛函式時,子類物件的記憶體布局
  • 單一繼承關系下,父類不帶虛函式,子類都帶虛函式時,子類物件的記憶體布局

多重繼承資料成員布局與this指標偏移話題

  • 子主題 1
  • 子主題 2
  • 子主題 3
  • 子主題 4

虛基類與虛繼承

  • 虛基類/虛繼承的提出(為了解決3層結構中孫子類重復包含爺爺類成員的問題)
  • 虛基類探討
  • 兩層結構的虛基類表5-8位元組內容分析
  • 三層結構的虛基類表1-4位元組內容分析

成員變數地址,偏移與指標話題深入探討

  • 物件成員變數記憶體地址及其指標(物件的成員變數是有真正的地址的,這與變數的偏移值不同)
  • 成員變數的偏移值及其指標(即:每個資料成員距離物件首地址的距離)
  • 沒有指向任何資料成員變數的指標(通過物件名/物件指標接成員變數指標的一種方式訪問成員變數)

函式語意學

普通成員函式呼叫方式(編譯器在形參上隱藏了一個this指標,性能上和呼叫全域函式差不多)

虛函式,靜態成員函式呼叫方式

class A
{
public:
int a;
virtual void fun()
{
printf("%p\n", this);
fun1();//直接呼叫
A::fun1();//走虛函式表
}

virtual void fun1()
{
	printf("%p\n", this);
}

};

int main()
{
A obj;
obj.fun();
A *obj1 = new A();
obj1->fun();
}

  • 虛函式呼叫方式

    • 通過物件呼叫是直接呼叫,和呼叫全域函式性能一樣
    • 通過指標呼叫是走虛函式表
    • 虛函式內呼叫另一個虛函式,如果用類名,則是采用全域函式呼叫方式,自己用函式名則是走虛函式表呼叫方式
  • 靜態成員函式呼叫方式

虛函式地址問題的vcall引入(為了解決多重繼承中this指標調整問題)

靜動態型別系結

  • 靜態型別與動態型別
  • 靜態系結與動態系結
  • 繼承的非虛函式坑
  • 虛函式的動態系結
  • 重新定義虛函式的預設引數坑
  • c++中的多型性(走虛函式表肯定是多型)

單繼承下的虛函式特殊范例演示

多重繼承虛函式深釋,第二基類與虛析構必加

  • 多繼承下的虛函式
  • 如何成功洗掉用第二基類指標new出來的子類物件
  • 父類非虛解構式時導致的記憶體泄漏演示

多繼承第二基類虛函式支持與虛繼承帶虛函式

  • 多重繼承第二基類對虛函式支持的影響(this指標調整的作用)
  • 虛繼承下的虛函式

RTTI運行時型別識別與存盤位置

  • 子主題 1
  • 子主題 2
  • 子主題 3

函式呼叫,繼承關系性能說

  • 函式呼叫中編譯器的回圈代碼優化
  • 繼承關系深度增加,開銷也增加
  • 繼承關系深度增加,虛函式導致的開銷增加

指向成員函式的指標以及vcall細節談

  • 指向成員函式的指標

    • 指向成員函式的成員函式指標(這也體現了,為什么成員函式指標呼叫成員函式需要物件的介入,因為,成員函式的呼叫需要一個隱藏的this指標)
    • 指向靜態成員函式的函式指標(不需要this指標)
  • 特殊代碼分享(不通過物件也可以實作成員函式的呼叫()不需要this指標)

  • 指向虛函式的成員函式指標及vcall談

    • 指向虛函式的成員函式指標(虛函式的呼叫也是需要this指標的)
    • vcall(有時我們列印虛函式的地址不是真正的虛函式地址,而是vcall的地址,vcall里放著虛函式在虛函式表里的偏移值,引入vcall是編譯器的一種做法)
  • vcall在繼承關系中的體現(有虛函式)

inline函式擴展細節(是否真的行內取決于編譯器)

  • 形參被對應的實參取代
  • 區域變數的引入(帶來了性能的消耗)
  • inline失敗情形(例如:遞回)

物件構造語意學

繼承體系下的物件構造順序

  • 物件的構造順序(從父到子,析構則相反)
  • 建構式里呼叫虛函式(直接呼叫,不是走虛函式表)

物件復制語意學與解構式語意學

  • 物件的默認復制行為(簡單的按值拷貝)

  • 拷貝賦值運算子與拷貝建構式

  • 如何禁止物件的拷貝構造和賦值

    • 宣告為private,只寫宣告,不寫函式體
    • c++11提供的delete關鍵字
  • 解構式語言(編譯器默認提供解構式的幾種情況)

    • 在繼承體系中,父類帶解構式,如果子類不帶解構式,編譯器會默認合成一個
    • 在一個類中,如果帶有一個型別別的成員變數,并且這個成員變數帶有解構式,

區域物件,全域物件的構造和析構

  • 區域物件的構造和析構(建議現用現定義,減少不必要的構造和析構)
  • 全域物件的構造和析構(main函式執行前就開始構造了,main函式結束以后,執行解構式)

區域靜態物件,物件陣列的構造析構和記憶體分配

  • 區域靜態物件的構造和析構(一個區域的靜態物件,如果多次使用,則只會構造一次,編譯器采取了標記的方法,以便防止靜態的區域物件構造多次,)
  • 物件陣列的構造和析構(靜態物件陣列到底在編譯時,分配了多少給位元組,這并不取決于你的陣列有幾個元素,而是取決于你的程式干了什么事,這是編譯器的一個智能做法,)

new與delete高級話題

  • new/delete的認識

    • malloc0個位元組的話題
  • 多載new/delete

    • new/delete細節探討

      • new一個類加括號和不加括號的區別

        • 類是空時無區別
        • 類A中有成員變數則:帶括號的初始化會把一些和成員變數有關的記憶體清0,但不是整個物件的記憶體全部清0
        • 類有建構式 得到的結果一樣
      • new干了什么

        • 呼叫operator new(malloc)
        • 呼叫了類的建構式
      • delete干了什么

        • 呼叫了·類的解構式
        • 呼叫了operator delete(free)
    • 多載operator new/operator delete

  • 嵌入式指標與記憶體池

臨時性物件的詳細探討

模板實體化語意學

模板及其實體化詳細分析

  • 函式模板

  • 類模板的實體化分析

    • 類模板中的列舉型別
    • 類模板中的靜態成員變數
    • 類模板的實體化
    • 成員函式的實體化
  • 多個源檔案中使用類模板

炫技寫法

  • 不能被繼承的類

    • c++11的final
    • 友元函式+虛繼承
  • 類外呼叫私有虛函式(一個private的虛函式可以呼叫嗎?可以使用特殊寫法進行呼叫)

在這里插入圖片描述

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

標籤:其他

上一篇:ensp三層架構實驗

下一篇:QGC地面站手把手教你改——電子羅盤儀表盤如何變刻度尺平移(雙儀表變單儀表)

標籤雲
其他(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