1.如果要在多個變量中使用一個const變量,可以在一個頭文件中定義,然后再其他文件中include<> 或者可以在c++的源文件中定義,然后才其他源文件中extern
2.標準頭文件用#inclue<>
自定義的頭文件用 #include “”
3.預防多次包含偶同一頭文件
#ifndef SALE
#define SALE //表示接受一個名字并定義該名字為預處理器變量
define of class and relate function
#endif
4.迭代器iterator的begin()操作返回的迭代器容器的第一個元素,end()返回容器的迭代器指向容器最后一個元素的下一個元素
5.如果不改變容器的內容,只做讀操作,使用const_iterator,
區別于const 的iterator,聲明一個const 迭代器,必須初始化,且一旦初始化后就不能改變。
6.迭代器的算術操作
iter + n 產生一個新的迭代器,位置指向iter指向元素之后n各的位置
iter1 - ite4r2 返回兩個迭代器對象的距離
7.任何改變vector長度的操作都會使已存在的迭代器失效,如push_back
8.指針的初始化
0
類型匹配的對象的地址
另一對象之后的下一地址
同類型的另一個有效指針
9.void* 指針可以保存任何對象的地址
表明指針只與一個地址相關,并不知道地址上所存的對象類型,不能用 void *操縱它所指的對象
10. #include <cstddef>
size_t unsigned 用來指明數組的長度
ptrdiff_t unsigned 用來指明指針的距離
11
指向const對象的指針
const double * cptr;
并不是指針本身是const的,而是所指的對象是const的,不能通過cptr修改所指對象的值,也不能把const對象的地址賦值給非const指針,
const 指針
int *const p = #
必須在定義時初始化。
指向const 對象的const 指針
const double *const ptr = π
12.string .c_str()返回const char 類型的指針
13sizeof返回size_t類型,計算數組元素的個數
n = sizeof(arr)/sizeof(*arr);
14.算術轉換
int + double -> double
float + double -> double
int = double -> int
float = double -> float
chat + float -> float
short + long -> long
int + unsigned long -> unsigned long
15 強制類型轉換
const_cast<>()轉換掉表達式的const性質
static_cast<>()很適合將一個較大的類型轉換成一個較小的類型。
16.函數的參數
int fun(int *p) 可以改變指針所指的對象的值
int fun(int *p) 如果保護指針所指的參數的值,要加上const int f(const int *p)
void fun(const int i) 不能改變實參的的局部副本,can read but can't write to i ;
17 引用
引用形參直接關聯到所綁定的對象.void swap(int &a , int &b)
像函數傳遞大型對象的時候,利用const引用避免復制,
復制龐大而復雜的值有昂貴的開銷。為了避免傳遞副本的開銷,可將形參指定為引用類型。對引用形參的任何修改會直接影響實參本身。應將不需要修改相應實參的引用形參定義為 const 引用 |
非const引用的形參只能與同類型的非const的對象關聯.
18 數組形參的定義
void f (int *)
void f (int [])
void f (int [10])
以上三種都等價為 void f(int *)
19 通過引用傳遞數組
void f(int (&arr)[100])
傳遞的是數組的引用本身,數組大小成為形參和實參的一部分,編譯器會檢查兩者是否匹配。
29返回值
返回非引用類型,函數會在調用出將函數返回值復制給臨時對象。
返回引用返回的是對象本身,不要返回局部對象的引用
const string &f(const string & s)
{ string ret = s; return ret ;}//err
不要返回指向局部對象的指針(懸垂指針)
30默認實參
string ScreenInit(string::size_type with = 24 ,string::size_type heigth = 59 );
string screen = ScreenInit();
screen = ScreenInit(20)
screen = ScreenInit(20,90)
40將函數指定為內聯是建議編譯器在調用點直接把函數代碼展開,內聯函數避免函數調用的開銷,內聯函數必須在頭文件中定義,
|
41const成員函數,在參數列表后面加上const ,則const成員函數不能改變調用該函數的對象。
42在局部聲明的變量名字將屏蔽在全局生命的同名名字,這個性質對函數名也同樣成立。
43.函數指針
bool (*pf)(const string &, const string &); typedef bool (*cmpFcn)(const string &, const string &); |
圓括號不可以省略。 函數指針只能通過同類型的函數或函數指針或 0 值常量表達式進行初始化或賦值 |
|
|
44.IO對象
IO對象不可復制或賦值,不可以存在vector等容器中.
形參或返回類型也不能為流類型。如果需要傳遞或返回 IO 對象,則必須傳遞或返回指向該對象的指針或引用 ofstream &print(ofstream&); 45.輸出緩沖區的管理
統將字符串字面值存儲在與流 os 關聯的緩沖區中。下面幾種情況將導致緩沖區的內容被刷新,即寫入到真實的輸出設備或者文件
程序正常結束。作為 main 返回工作的一部分,將清空所有輸出緩沖區。 在一些不確定的時候,緩沖區可能已經滿了,在這種情況下,緩沖區將會在寫下一個值之前刷新。 用操縱符顯式地刷新緩沖區,例如行結束符 endl。 在每次輸出操作執行完后,用 unitbuf 操作符設置流的內部狀態,從而清空緩沖區。 可將輸出流與輸入流關聯(tie)起來。在這種情況下,在讀輸入流時將刷新其關聯的輸出緩沖區。 cout << "hi!" << flush; // flushes the buffer; adds no data cout << "hi!" << ends; // inserts a null, then flushes the buffer cout << "hi!" << endl; // inserts a newline, then flushes the buffer unitbuf 操縱符。這個操縱符在每次執行完寫操作后都刷新流: cout << unitbuf << "first" << " second" << nounitbuf; 當輸入流與輸出流綁在一起時,任何讀輸入流的嘗試都將首先刷新其輸出流關聯的緩沖區。標準庫將cout 與 cin 綁在一起,因此語句:cin >> ival;導致 cout 關聯的緩沖區被刷新。
|
|
|
|
46stringstream 可將多種數據格式與string類型進行自動轉化
47成員函數:
在類內部定義的函數默認為inline. 將關鍵字const加在形參列表之后,const成員函數不能改變其所操作對象的數據成員。 48const成員函數返回*this
普通非const成員函數的this是一個指向類類型的const指針,可以改變this指向的值,不能改變this所保存的地址,而const成員函數,this的類型是一個指向const類型對象的const指針。const成員函數只能返回*this作為const 引用, 50mutable數據成員
將類成員聲明為mutable,任意const對象,或者const函數丟可以改變它的值 51構造函數
不管成員是否在構造函數中顯示初始化,類類型的數據成員總是在初始化階段初始化。在構造函數初始化列表沒有顯示提及的每個成員,運行該類型的默認構造函數,內置貨符合類型的初始值依賴于對象的作用域:在局部作用域這些函數不被初始化,在全局作用域被初始化為0. 沒有默認構造函數的類類型成員,以及const或引用類型的成員,都必須在初始化列表進行初始化。 按照與聲明一致的次序編寫構造函數初始化列表是個好主意。 52默認構造函數
定義一個對象是沒有提供初始化式,就是使用默認構造函數,為所有形參提供默認實參的構造函數也定義了默認構造函數 53static成員和成員函數
非static成員存在于每個類類型的對象中,而static成員獨立于該類的任意對象而存在,美國各static數據成員是與該類關聯的對象。 static成員函數沒有this形參,可以直接訪問所屬類的static成員,但是不能直接使用費static成員 54復制構造函數
復制構造函數只有一個形參,該形參(常用const修飾)是對該類類型的引用,當定義一個新對象并用一個同類型的對象對他進行初始化的時候,是顯式得使用復制構造函數,將該類型的對象傳遞給函數uo從函數返回該類型的對象的時候,是隱式得使用復制構造函數。 string null_book = "9-999-99999-9"; // copy-initialization string dots(10, '.'); // direct-initialization string empty_copy = string(); // copy-initialization string empty_direct; // direct-initializat |
| 55為了避免復制,類必須顯式聲明復制構造函數為private 然而這樣類的友元和成員仍可以復制,如果要連友元和成員的復制也禁止,可以定義一個private的復制構造函數但不對其定義。
56賦值操作符重載 當操作符為成員函數的時候,第一個操作數隱式地綁定到this指針,即this綁定到左操作數的指針,右操作數一般為const傳遞的引用,復制操作返回同一類型的引用。
57析構函數 析構函數沒有參數也不能重載,即使我們編寫了自己的析構函數,合成析構函數仍然運行,合成析構函數不刪除指針成員所指向的對象,合成析構函數按對象創建的時間逆序撤銷每個非static成員。
58重載操作符 賦值(=)、下標([])、調用(())和成員訪問箭頭(->)等操作符必須定義為成員,將這些操作符定義為非成員函數將在編譯時標記為錯誤 | |
|
|
復合賦值操作通常定義為類的成員,但不一定要定義成類的成員
改變對象狀態或與給定類型緊密聯系的操作,如自增,自減和解引用操作,都應該定義為類的成員
對稱的操作符,如算術操作符,相等操作度關系操作符和類操作符,最好定義為普通非成員函數
IO操作必須為非成員函數
賦值必須返回對*this的引用
operator + 返回一個對象,而operator +=返回一個引用
定義下標操作符[]時,一般定義兩個版本,一個為非const成員返回引用,另一個為const成員返回const引用。
class S
{
public :
int &operator[] (const size_t);
const int &operator[]( const size_t)const;
}
59定義轉換和操作符
(1)不要定義相互轉換的類,機如果類Foo具有接受類 Bar的對象的構造函數,不要再為類Bar定義到類型Foo的構造函數
(2)避免到內置算術類型的轉換,具體而言,如果定義到算術類型的轉換,不要定義接受算術類型的操作符的重載版本,如果用戶需要使用這些操作符,轉換操作副將轉換你所定義的類型的對象,然后可以使用內置操作符
不要定義轉換到一個以上算術類型的轉換,讓標準抓包換提供到其他算術類型的轉換
60基類成員函數
成員函數默認為非虛函數,對f非虛函數的調用在編譯時確定,除了構造函數,其他非static成員函數都可以是虛函數,虛函數運行時動態綁定,
61訪問控制和繼承
public private和protect
用戶可以訪問類的public成員,不能訪問private成員
private成員只能由基類的成員或友元訪問
派生類對象對基類的public和private成員的訪問權限和程序中任意其他部分一樣,可以訪問public不能訪問private。
protect成員不能被類的用戶訪問,可以被類的派生類訪問,派生類只能通過派生類的對象訪問基類的protect成員,派生類對基類類型對象的proteced成員沒有訪問權限
62虛函數動態綁定
出發動態綁定的兩個條件:1.指定為virtual,2,必須通過基類類型的引用或指針進行調用
63派生類虛函數調用基類版本的時候,必須顯式使用作用域操作符
64虛函數的基類版本和派生類版本使用不同的默認實參,通過基類的指針或引用調用,但實際執行的是派生類的版的時候會出問題,因為虛函數基類版本定義的默認實參會傳給派生類的版本。
65pubilc,private,和protect繼承
public inheritance :基類的public成員為派生類的public成員,基類的protect成員為派生類的protect成員
private inheritance:基類的所有成員在派生類中為private成員
protect inheritance:基類的public成員和protect成員在派生類中為protect成員
派生類不能訪問基類的protect成員
類的默認的繼承為private,struct默認的繼承為public的
65繼承和static成員
如果基類定義了static成員,則整個繼承層次中只有一個這樣的成員,無論基類派生出多少個派生類,沒個static成員只有一個實例
66派生類到基類的轉換
可以用派生類的對象對基類對象進行賦值或初始化
引用轉換不同于轉換對象,將派生類對象傳給希望接受基類對象的函數是,該派生類對象的基類部分被復制到形參
67從基類到派生類的自動轉換時不存在的
68如果派生類顯示定義復制構造函數或賦值操作符,則該定義將完全覆蓋默認定義,必須顯示的調用繼承的復制構造函數和賦值操作符對基類成分以及類自己的成員進行復制或賦值。
class Derived{
public:
Derived(const derived &d):Base(d) { other menber initialization}
}
69即使沒有工作要做,繼承層次的跟類也應該定義一個虛析構函數
70構造函數不能是虛函數,復制操作符最好不要是虛函數(虛函數的形參列表等必須相同,會引起混淆)
71如果在構造函數或者析構函數效用虛函數,則調用的是為構造函數或析構函數自身類型定義的版本。
72與基類成員同名的派生類成員將屏蔽對基類成員的直接訪問,成員函數名也一樣。
73重載成員函數
如果派生類定義了重載成員函數,則通過派生類類型之unengfangwen派生類中重定義的那些成員,如果要訪問,加個using聲明(?)
74容器與繼承
如果定義了一個基類類型的容器,派生類對象在賦值給容器的時候,對象的派生屬性會被切掉,只保留基類的成分
75c++繼承如火確定函數調用
1. | 首先確定進行函數調用的對象、引用或指針的靜態類型。
| 2. | 在該類中查找函數,如果找不到,就在直接基類中查找,如此循著類的繼承鏈往上找,直到找到該函數或者查找完最后一個類。如果不能在類或其相關基類中找到該名字,則調用是錯誤的。
| 3. | 一旦找到了該名字,就進行常規類型檢查,查看如果給定找到的定義,該函數調用是否合法。
| 4. | 假定函數調用合法,編譯器就生成代碼。如果函數是虛函數且通過引用或指針調用,則編譯器生成代碼以確定根據對象的動態類型運行哪個函數版本,否則,編譯器生成代碼直接調用函數。
|
|
|
76模板
模板形參是const引用
函數體中的測試之用 < 比較
多個類型形參的實參必須完全匹配
77異常
異常通過拋出(throw)對象引發,執行throw的時候,不會執行在throw后面的語句,而是將控制從throw轉移到匹配的chatch。
處理異常的時候會四方局部存儲,被拋出的對象不能再局部存儲,而是用tw表達式出事話一個床位異常對象的特殊對象。
當拋出一個表達式的時候,被拋出的對象的靜態編譯時的類型將決定異常對象的類型,最好不要拋出指針
當catch結束的時候,在緊接在與該try塊相關的最后一個cahtch子句只有的點繼續執行
一個快可以通過調用new動態分配內存,如果該塊因異常退出,編譯器不會刪除該指針,已分配的內存將不會釋放。
在查找匹配的catch期間,不是尋找最佳匹配,而是選中第一個找到的可以處理該異常的cahtch
如果被拋出的對象是派生類類型的,但由接受基類類型的catch處理,cahtch將不能使用派生類特有的所有成員,所以cahtch子句處理因繼承而相關的類型的異常,它就應該將自己的形參定義為引用。
重新拋出throw,當catch無法處理的時候,將重新拋出throw將異常傳遞給函數調用鏈中更上層的函數
exception類所地被你故意的唯一操作時一個名為what的虛成員,該函數返回,const char*
可能存在異常的程序以及分配資源的程序應該使用類來管理那些資源,如果函數因異常而提早退出,編譯器就運行類的析構函數最為異常處理過程的一部分。
77auto_ptr
為異常安全的內存分配使用auto_ptr,
當復制auto_ptr對象或者將它的值付給其他arto_por對象的時候,將基礎對象的所有權從原來的auto_ptr對象傳給副本,原來的auto_ptr對象重置為未綁定狀態
賦值操作刪除做操作數指向的對象
應該只用get詢問auto_ptr對象或者使用返回的指針值,不能用get作為創建其他auto_ptr的實參
調用auto_ptr的reset的時候,會刪除auto_ptr所指向的對象。
不要使用兩個auto_ptr指向同一對象,不要使用auto保存對象保存指向動態分配數組的指針,以為當auto_ptr被刪除的時候,它使用的是delete操作符,不是delete[]
78c++內存分配方式
(1)allocator 類
(2)標準庫中的oprator new和operator delete函數
79new operator(primerl里面成為operator new 函數) operator new 和placement new
new operator :
(1)string *sp = new string("abc");
1.先調用operator new 的標準庫函數分配足夠大的原始的為類型化的內存2.以保存指定內存的一個對象;運行該類型的一個構造函數,用指定初始化式構造對象,3.返回指向新分配內存并構造的指針。
(2)operator new:
void *operator new(size_t)
void *operator new[](size_t)
獲得未構造的內存
operator detete不會調用析構函數,只會釋放指定內存
(3)placement new:(定位new)
new (place_address)type
place_address為一個指針,
80運行類型識別(RTTI)
(1)typeid操作符,返回指針或引用類型所致對象的實際類型
base *pb;
derived *pd;
if(typeid(*pb) == typeid(*pd))
{
//測試對象動態類型
}
if(typeid(pb) == typed(pd))
{
//測試指針的靜態編譯的類型,永遠不等
}
(2)dynamic_cast操作符,將基類類型的指針或引用安全轉化為派生類類型的指針或引用
dynamic_cast<*derived>(BasePtr)
81類成員函數指針和成員指針
類數據成員指針定義:
類型 類名::* name
成員函數指針定義
返回類型 (類名::指針名 *)(形參列表)
82volatile限定符
直接處理硬件的程序常具有這樣的數據成員,它們的值由程序本身直接控制之外的過程所控制。例如,程序可以包含由系統時鐘更新的變量。當可以用編譯器的控制或檢測之外的方式改變對象值的時候,應該將對象聲明為 volatile。關鍵字 volatile 是給編譯器的指示,指出對這樣的對象不應該執行優化。 |