基礎知識點
-
C++中對象數組在定義的時候全部進行實例化(與Java不同,Java相當于只是定義了一個指針數組,沒有進行實例化)
-
程序的三種基本控制結構是:順序結構、循環結構、選擇結構
-
一個C++程序開發步驟通常包括:編輯、編譯、鏈接、運行和調試
-
面向對象程序設計主要有四個特點:抽象、繼承、多態、封裝
-
C++中的兩種代碼復用方式:繼承和模板
-
類是某一類對象的抽象,對象是類的具體實例,類和對象的關系是一種數據類型與變量的關系
-
構造函數的作用是再創建對象的時候初始化對象的數據成員
-
默認構造函數有兩種:無參構造函數和所有參數都有默認值的構造函數(兩者不能同時存在)
-
常對象只能調用它的常成員函數,不能調用普通函數
-
如果一個類沒有定義默認構造函數,但是定義了其他構造函數(有參的),編譯器將不會自動生成默認構造函數(此時如果派生類中沒有顯式調用父類的有參構造函數將會編譯出錯)
-
cin
是istream
類的對象 -
轉換構造函數只有一個參數,可以隱式地將其他類型轉換成該類類型。可以用
explicit
杜絕編譯器的隱式轉換。與之對應的還有類型轉換函數,可以將類類型轉換成其他類型。詳見:C++轉換構造函數和類型轉換函數 -
析構函數的作用是提供一個在對象刪除前釋放該對象占用資源的機會
-
構造函數順序和析構函數相反
-
構造函數順序:虛基類->普通基類->成員對象->當前類詳見:C++派生類含有成員對象構造函數析構函數順序
-
拷貝構造函數的使用:
- 復制對象把它作為參數傳遞給函數
- 復制對象從函數返回這個對象
- 初始化另一個對象(必須是定義的時候,賦值不算)
-
重載和函數的返回值沒有關系,只和函數名以及函數參數列表有關。派生類中只要函數名字和基類相同就會重寫。重寫以后我們將無法直接通過派生類對象訪問基類的同名函數,只能通過
基類名::
顯式訪問 -
需要注意保護的成員我們也不可以通過對象訪問
-
this指針:在每一個非靜態成員函數中都包含一個特殊的指針,這個指針的名字是固定的,稱為
this
指針。他是指向本類對象的指針,他的值是當前被調用的成員函數所在對象的起始地址。這樣同一個類創建的多個對象共用同一份成員函數的拷貝也知道是取哪一個對象的成員數據。如果派生類中含有和基類相同名字的成員函數就會重寫 -
要實現動態聯編一般通過對象指針調用虛函數
-
在C++面向對象程序設計框架中類是程序的基本組成單位
-
delete
只能釋放用new
運算符分配的內存 -
靜態數據成員只能在類外定義和初始化,格式為
數據類型 類名::變量名=初值;
不需要
static
關鍵字 -
編譯器自動生成的拷貝構造函數可能會產生什么問題:當對象有指針數據成員,并用它初始化同類型的另一個對象時,缺省的拷貝構造函數只能將對象的數據成員賦值賦給另一個對象,而布恩那個將該對象中指針所指向的內存單元也復制一份。這樣就可能出現同一內存單元釋放兩次,或者傳遞參數后實參中的地址無效,導致程序運行出錯。
-
使用虛基類是為了解決多重繼承中的二義性問題
-
靜態函數沒有
this
指針 -
描述友元函數的時候應該說明是哪個類的友元函數
-
拷貝構造函數同樣是構造函數,因此和構造函數的調用順序一樣,調用順序為虛基類->基類->成員對象->拷貝構造函數。
#include<iostream>
#include<string>using namespace std;class A
{int val;
public:A(){val = 0; cout << "A():" << val << endl;}A(int v){val = v; cout << "A():" << val << endl;}
};class B :public A
{A obj;
public:B(int v1, int v2) :A(v1), obj(v2){cout << "B()" << endl;}B(const B& x){cout << "Copy B()" << endl;}
};int main()
{B obj1(2, 3);B obj2(obj1);
}
運行結果:
- 結構化的程序設計與面向對象的程序設計:結構化的程序設計將數據和對數據的操作分離,程序是由一個個函數組成的。面向對象的程序設計將數據和操作封裝在一起,程序是由一個個對象組成的,對象之間通過接口進行通信,它能夠較好地支持程序代碼的復用。
- 類和結構體都是C++中用戶自定義的數據類型。
- 從實現的角度來講,多態性可以劃分為兩類:靜態多態性、動態多態性
虛函數
- 不能聲明為虛函數的函數:普通函數、構造函數、靜態函數、內聯成員函數、友元函數。成為虛函數的特點是:可以被重寫/重載,可以在運行時才確定。詳見:C++不能被聲明為虛函數
- 虛函數用于實現動態多態性
- 純虛函數實在基類中說明的虛函數,它在該基類中沒有定義具體的操作內容。含有純虛函數的類稱為抽象類,抽象類不能被實例化(可以定義指針和引用),必須由他的派生類完成對純虛函數的定義
友元函數
- 友元函數不是成員函數,破環隱蔽性,盡量減少使用。友元函數可以提高程序運行效率,節約了調用類成員函數的開銷
運算符重載
- 不能進行重載的運算符:
.
成員訪問運算符.* ->*
成員指針訪問運算符::
域運算符?:
條件運算符#
預處理運算符,詳見:【C++學習筆記四】運算符重載 - 運算符重載以后,要求其保持原來的操作數個數、優先級、結合性、語法結構
- 后綴自增運算符的第一個參數(如果還有其他參數的話)必須是
int
,這樣做是為了區分前綴和后綴 - 運算符函數可以重載為成員函數、友元函數和普通函數。但是有的運算符只能重載為成員函數:
= [] () ->
模板
- 類模板的使用是將上是將類模板實例化成一個類
- 對于模板類我們只有要用到的時候才會進行實例化:
- 模板類作為函數聲明的參數不會實例化
- 定義模板類的指針和引用不會實例化
- 但是如果進行定義時(其他類中含有模板類成員、函數參數或者函數體中含有模板類)以及模板類指針需要訪問成員時都會進行實例化。
- 需要知道模板類大小的操作都需要進行實例化。如
new sizeof
運算符等。詳見:C++類模板實例化條件
繼承、基類指針指向派生類對象
- 私有繼承不允許基類指針指向派生類
- 基類指針只能訪問到基類中含有的公有成員
- 當用基類指針指向派生類對象在動態分配堆上內存的時候,析構函數必須是虛函數
詳見:C++基類指針指向派生類(指針)
流輸入流輸出
- 重載流插入運算符
<<
重載流提取運算符>>
cin
是istream
的對象,cout
是ostream
的對象
const的用法
可以閱讀這個博客,已經將的超級詳細了:傳送門