c++基礎(上) 聽課流水賬
1、pass by value / pass by pointer / pass by reference
pass by value:實參和形參不是同一個值,因此交換的是形參的值,當函式swap結束後,a和b的值並沒有發生交換
pass by pointer and pass by reference :實參和形參是相同的。
2、動態記憶體
申請失敗的返回值是 0 而不是 NULL, null在cpp中廢止了。
申請一個長度我10,初始值都為0的空間
int *num= new int[10]();
3、對比new和malloc
4、cpp記憶體模型
記憶體模型:棧、堆、靜態區、常量區。
5、陣列記憶體模型
5、const char * / char * const / char const *
在c中,const是只讀變數,cpp裡const指的是常量。
6、常量指標和指標常量
下圖為p1常量指標——p1所指地址上的內容不可以通過p1做出改動
下圖p2為指標常量——p2所指的地址不可以發生改動
陣列名就是一個指標常量
例項:
下圖中的int const* pi和const int* pci是一樣的
7、UML類圖
一些編碼規範:類名首字母大寫;
8、匿名物件
9、訪問物件成員
返回值型別 類名 : : 函式名
10、cpp的string型別
11、訪問器與更改器
12、同名遮蔽
#include "pch.h"
#include<iostream>
using namespace std;
class Foo {
public:
int x;
int y;
Foo() {
x = 10;
y = 10;
}
void p() {
int x = 20;
cout << x << endl;
cout << y << endl;
}
};
int main(int argc, char **argv)
{
Foo foo;
foo.p();
return 0;
}
執行結果: 20 10
13、成員函式的this指標
14、避免同名遮蔽的簡單方法
15、物件陣列
#include "pch.h"
#include <iostream>
using namespace std;
class C {
public:
C(int i) { //帶參建構函式
std::cout << "\t parameterized ctor" << std::endl;
}
C() { //無參(預設)建構函式
std::cout << "\t default ctor" << std::endl;
}
C(const C& c) { //拷貝建構函式
std::cout << "\t copy ctor" << std::endl;
}
C& operator =(const C& c) { //過載了類C的賦值運算子,觀察main()中的物件賦值現象
std::cout << "\t assignment operator" << std::endl;
return *this;
}
};
int main() {
cout << "C c1;" << endl;
C c1; //呼叫無參(預設)建構函式
cout << "C c2(2);" << endl;
C c2(2); //呼叫有參建構函式
cout << "C c3 = c1;" << endl;
C c3 = c1; //呼叫拷貝建構函式
cout << "C c4 = C();" << endl;
C c4 = C(); //編譯器將之等價為 C c4;
cout << "C c5 = C(5);" << endl;
C c5 = C(5); //編譯器將之等價為 C c5(5);
cout << "C c6(c1);" << endl;
C c6(c1); //呼叫拷貝建構函式
cout << "C c7(C(7));" << endl;
C c7(C(7)); //編譯器將之等價為 C c7(7);
cout << "C c8[4] = {C(), C(18), c7};" << endl;
C c8[4] = { C(), C(18), c7 }; //c8中的4個元素初始化時,是看做4個獨立的物件處理:
//C c80 = C(); 調預設建構函式
//C c81 = C(18); 調有參建構函式
//C c82 = c7; 調拷貝建構函式
//C c83 = C(); 調預設建構函式
cout << "C c9; c9 = C(9);" << endl;
C c9; //呼叫預設建構函式
c9 = C(9); //先呼叫有參建構函式構造一個匿名物件C(9),然後呼叫賦值運算子將該匿名物件賦值給c9
return 0;
}
16、封裝
當你的資料域是物件型別的時候,他必須放在建構函式的初始化列表裡面進行構建,除非這個資料域的物件型別中有預設的無參建構函式。
17、不可變物件
定義:建立之後,不可變物件不可修改,除非通過成員拷貝。
如何讓類“不可改變”:
1、資料域均設定為私有屬性。
2、沒有介面,使得外部可以呼叫來更改你的資料。
3、也沒有能夠返回可變資料域物件的引用或指標的訪問器。
不可變類的一個特徵是執行緒安全的,所以他有用。
18、避免多次宣告
19、static
本檔案內的static函式只允許本檔案訪問
下圖中的靜態資料成員numberofObjects,被類Circle的物件們共享。
靜態成員變數只能放在所有函式的外面進行初始化
numberOfObjects一定要初始化,不然會報錯
20、使用靜態成員函式的規則
靜態成員函式的訪問規則
21、解構函式
22、拷貝構造
拷貝建構函式的形式以及何時會呼叫拷貝建構函式
注意下圖右下角的賦值 x c = b; ,構造出的c裡面傳入的是預設引數 1 。
淺拷貝和深拷貝(類中資料成員如果含有指標,一定要自己寫拷貝建構函式,因為編譯器預設給生成的是淺拷貝版的拷貝建構函式,容易出問題的)
拷貝建構函式是一種特殊的建構函式
23、寫一個類,實現棧的功能
24、寫一個類,實現vector
24、一些編碼規範
25、繼承
派生類不能繼承的是:
1、建構函式(cpp 11 中已經允許)
2、解構函式
3、友元函式
4、拷貝賦值函式
派生類建構函式呼叫基類建構函式的方法 :
若沒有顯示的呼叫基類的建構函式,則編譯器預設呼叫無參的基類建構函式
(如果你寫的建構函式有參,則編譯器會報錯,因為找不到無參的積累建構函式)
構造和析構的順序
26、重定義
派生類對父類的同名函式內容進行修改。不修改的地方:
1、返回值型別
2、傳入的引數
3、函式名
區分重定義和過載
27、繫結
基類中定義的虛擬函式,在派生類中的同名函式會自動變成虛擬函式,無需新增virtual關鍵字。
總結靜態繫結和動態繫結
下面四張圖的總結:
訪問方式 | 訪問物件 |
物件呼叫(p.f()) | 子類同名函式 |
父類指標指向子類物件(圖2) | 父類同名函式 |
父類指標指向子類物件(圖3) | 子類的同名虛擬函式 |
28、protected
protected成員可以被類內成員函式直接獲取,不可以通過物件來獲取。
29、幾種繼承方式的總結
30、抽象類與純虛擬函式
抽象類(有純虛擬函式的類是抽象類)不能被例項化
31、動態轉換
32、向上轉型和向下轉型
向上轉型可不使用dynamic_cast,而是隱式轉換
向下轉型必須使用dynamic_cast進行顯示轉換。
33、typeid運算子——用於獲取物件所屬的類的資訊
可將派生類物件擷取,只是用繼承來的資訊;但是不能將基類物件加長,無中生有變出派生類物件。(如下圖:circle是派生類)