1. 程式人生 > 其它 >解決部落格園TinyMCE模式下內建插入程式碼塊功能不支援Go語言的問題(兩個並不完美的解決方案)

解決部落格園TinyMCE模式下內建插入程式碼塊功能不支援Go語言的問題(兩個並不完美的解決方案)

C++基礎

public和protected和private三種繼承有什麼區別

三種繼承方式對於子類來說沒有任何區別,但是對於子類的例項化物件來講有區別。但是隻分為兩種,public一種和protected,private一種。後者會使子類的例項化物件無法訪問到基類的public成員。

protected和private會影響到子類的子類,即影響到孫子類。如果是protected繼承,那麼結果和public繼承一樣,public和protected屬性都能夠訪問,如果是private繼承,那麼孫子類無法訪問到基類的所有屬性,因為對他來說這些屬性在繼承至子類的時候已經變成了private

public繼承可以視為是is-a關係,而private繼承類似複合(has-a),但是又比複合更第一層

C++的記憶體結構使怎樣的

  • 堆區:編譯器自動分配釋放的區域,區域性變數和函式引數就儲存在堆區,離開作用域自動釋放
  • 棧區:程式設計師手動申請的區域,比如new和malloc
  • 全域性區:全域性變數和靜態變數存放的區,程式結束後才釋放
  • 程式碼區

New和Malloc的區別

最基本的,new是C++風格的記憶體申請,它是經過包裝的,比malloc更安全。

  • 使用new不需要指定需要分配多少空間,而malloc需要。同時new返回的是申請的物件的指標,而malloc返回的是void*,需要使用者自行轉換,這是不安全的,而new是型別安全的。如果new分配失敗了會丟擲bad_alloc異常,而malloc失敗了會返回NULL。如果new的是一個物件的話那麼他還會呼叫到它的建構函式

呼叫new/delete的過程

首先new會呼叫operator new來分配記憶體,然後會使用static_cast進行轉型,最後利用轉型後的指標來呼叫一波建構函式

operator new是一個可過載的函式,他的內部會呼叫malloc,若失敗了丟擲異常,成功了則分配一個指定的記憶體空間,然後返回一個空指標

delete的話會先執行解構函式,然後再執行operator delete

指標和引用的區別

指標使用的時候可以不需要初始化嗎,引用需要初始化

指標在執行過程中可能會成為野指標或者空指標

引用的本質可以看作是指標常量,因為它引用的目標不能更改,但是可以

static_cast和dynamic_cast的區別

static_cast可以說是適用於C風格的轉換,比如說double到float,轉換int到char,子類轉父類等等

dynamic_cast用於多型型別的轉換,同時它自帶IDE檢查,只能用於指標和引用的轉換

dynamic_cast自帶型別檢查,對於指標型別若失敗會返回nullptr,對於引用型別失敗會丟擲bad_cast異常

兩者都在編譯器層面都不支援無效的型別轉換,且dynamic_cast在轉換失敗時會返回一個nullptr,而static_cast不會,所以static_cast是不安全的。

reinterpret_cast用於指標型別的轉換

const_cast用於消除const限定符

memcpy和strcpy的區別?

  • mencpy能拷貝任意型別的資料,而strcpy只能拷貝字串
  • mencpy需要顯示指定拷貝的長度,而strcpy不需要,當他遇到/0的時候會自動停止,這種就可能會導致記憶體溢位

編譯期多型和執行期多型

通俗的來講這兩者的區別就是:應該呼叫哪一個過載?和 應該繫結哪一個虛擬函式?

編譯期多型是指不同的模板引數具現化導致呼叫不同的過載函式,STL就是靜態多型一個應用的例子,泛型程式設計。效率較高,但是除錯困難

  • 函式過載
  • 函式模板

執行期多型指利用查虛擬函式表實現的基類物件呼叫派生類的成員函式,執行時動態繫結,效率較低

  • 虛擬函式表

虛擬函式表

如果一個類至少一個虛擬函式的話,那麼這個類就擁有一張虛擬函式表,如果他有子類,那麼子類也會有一張虛擬函式表。

虛擬函式表可以看作是一個存放虛擬函式指標的陣列

每個類的例項化物件都會有一個指向該虛擬函式表的指標,虛擬函式表的指標是在類的建構函式中初始化的

函式簽名

函式名 函式引數 函式引數順序 所在的類 所在的名稱空間

C語言的函式簽名不包含函式引數和引數順序,所以C語言沒有函式過載

static

靜態全域性變數,靜態全域性函式,它們都是單檔案使用的

靜態區域性變數,重複宣告不會覆蓋其值

靜態成員變數和靜態成員函式:宣告週期比類長,每個類有一份,而不是每個類例項,每個類例項共享這一份。類內靜態成員函式可以訪問其他非靜態成員函式和變數,但是類內非靜態成員函式不能訪問類內靜態成員變數和函式

const

修飾變數

修飾指標:頂層指標(指標常量),指向的方向不能更改。底層指標(常量指標),指向的值不能更改

修飾函式引數

修飾函式返回值

修飾函式——常函式

inline

宣告和定義都在類內的成員函式預設是inline

行內函數在呼叫時與巨集呼叫一樣展開,不需要函式呼叫時引數的壓棧操作,減少了呼叫開銷

struct和class

預設成員訪問許可權,public和private;預設繼承許可權,public和private

class可用於模板中替代typename

其實現版本的C++中struct和class已經幾乎一致了,說使用區別的話那應該是為了相容C語言。struct可以成為一個單純的資料集合,或者說是POD,而類要擔負的就更多,比如做資料處理等等

Union

union中的資料型別是不允許具有建構函式的,可以允許POD的存在。Union中的資料存在於同一片記憶體中,至於提取出來什麼值看你使用什麼方法去解釋它

union U
{
    int a;
    char c;
};
int main()
{
    U u;
    u.c = '1';
    cout << u.c << endl;	// '1'
    u.a = 100;
    cout << u.c << endl;	// 'd'
}

友元

友元函式

友元全域性函式

class A
{
    friend void globalVisit();
    int data = 100;
    int showData() { return data;  }
};


void globalVisit()
{
    A a;
    a.showData();
}

其實這個函式寫在類A中也是可以的,但是它同樣不能直接訪問A物件的privateprotected物件

void globalVisit()
{
    // 不行
    cout << data << endl;
}

友元成員函式

首先B中被當成朋友的函式得是public的,其次該函式需要在類A聲明後再實現

class B
{
public:
    void visitFriend();
};

class A
{
    friend void B::visitFriend();
    int data = 100;
    int showData() { return data;  }
};

void B::visitFriend()
{
    A a;
    a.showData();
}

友元類

順序需要是先朋友再主人

class B
{
    void visitFriend()
    {
        A a;
        a.showData();
    }
};

class A
{
    friend B;
    int data;
    int showData() { return data;  }
};

記憶體對齊

會按照結構中最大的型別作為基準,進行整數倍的對齊

// 大小是16
union U
{
    int arr[3];
    double d;
};

// 大小是24
struct S1
{
    int arr[3];
    double d;
};

// 大小是12
struct S2
{
    char c1;
    int i;
    char c2;
};

強列舉型別

普通的列舉型別在同一個namespace中,是不能出現重名的,且能夠被隱式轉換為int型別的值

而強列舉型別(enum class)的列舉型別是唯一的,但仍可以顯示轉換為int,unsigned int等型別

enum class my_enum : unsigned int
{
    value1,     // 0
    value2,     // 1
    value3 = 100,
    value4 = 200,
    value5,     // 201
};