這幾天C++語法考試,記錄一下:html
a第一章:算法
1,面向對象程序設計的有點:數組
實現對現實世界客體的天然描述。app
可控制程序的複雜度。ide
可加強程序的模塊性。函數
可提升程序的重用性。this
可改善程序的可維護性。spa
第二章:設計
1,cin -> stdin; cout -> stdout; cerr->stderr;clog->stdprn,cerr和cout的區別就是他不可以被重定向。指針
2, 命名空間的聲明 namespace mfc {int inflag;} 同一個命名空間能夠定義屢次。
using 用多了會衝突。
3,cin>>x>>n,這個輸入到x,n主要是經過空格來隔開的。也是經過空格表示結束。
4,dec 十進制, oct八進制,hex十六進制,cout<<hex<<i<<endl;一旦進入這個狀態就不能改變了。例如,cout<<hex<<i<<endl; cout<<i<<endl; 兩個都是十六進制。
5,setw若是不夠大小的話不起做用,若是比原來的大的話從左邊填充。setw是一次性的,就是說若是輸出了,就不會見效了,必須從新來。例如,cout<<setw(3)<<3456,這個不會擴大,而cout<<setw(7)<<3456就會左邊填充空格,以後cout<<3456又回到wide = 0的默認值了。這個東西是iomanip文件中的,須要include <iomanip>
6,setprecision()這個在double地時候是表示留下幾位。例如,33.33 setprecision(2), 33.3,若是有fixed,就是小數點固定,就表示小數點後面幾位的。例如,33.3333 fixed + setprecision(2) 爲33.33 表示小數點以後的留下幾位。
7,ifstream fstr(path) ofstream istr(path)
8,const int* a 這個表示所指向的內容不會變。int* const a 表示指針a不能變。
9,float j = static_cast<float>(i). const_cast<int> 把const轉化成爲不一樣的。
if(typeid(*base) == typeid(Derived1)) {
Derived1 *derived1 = static_cast<Derived1*>(base);
derived1->showOne();
}
static_cast和dynamic_cast就是都是經過是基類轉化成爲派生類。可是static就是強轉化,而dynamic_cast是弱轉換。若是失敗會跑出bad_cast的異常。
若是device& x, dynamic_cast<deviceBase&>(x)....須要注意引用的應用。這裏面須要注意的是dynamic_cast<D> D 必定是引用和指針。
reinterpret_cast用於不一樣類型的轉換。
10,bool的地方也能夠用Int是否等於0來判斷。-1也是true。
11,string是以NULL爲結尾的。string s4(10,'X'); string s3 = s2; int 轉化成爲string 用<sstream>中的stringStream,由於是流.例如:
string str;
stringStream strStream;
int i = -1;
strStream<<-1<<endl;
strStream>>str;
cout<<str<<endl;
12,遍歷文件夾getline
#include <string>
#include <file>
using namespace std;
int main(char* args[])
{
string str;
ifstream input("C:\\source.txt");
ofstream output("C:\\dest.txt");
while(getline(input,str))
{
output<<str;
}
input.close();
output.close();
}
這裏須要注意,file的空間和getline的返回。
13,erase(開始位置,長度);insert(插入位置,插入的字符串);replace(替代位置,子竄大小。子串。),swap(字串),find("",startPos), 字符串支持 == > < != 這樣的操做。
14,int main(int argc,char * argc[]){...}
15, 引用,通常都是用於參數傳遞的時候用,這樣可以對這個參數進行修改。不能然會局部變量的引用。
16,inline函數的限制:
a,不能包括複雜的結構控制語句(while, switch)。
b,不能包括內聯函數自己。
c,不能是直接遞歸。(本身內部還調用本身的函數)
17,inline和宏的區別:
a,宏是預處理器進行替代,而inline是編譯實現的。inline有更強的約束性。
b,inline函數是真正的函數,是準尋函數類型和做用與規則。
注意:類中的inline函數通常都是在.h文件中直接定義。
18,函數簽名不包括返回值,因此不能只看返回值。
19,函數的默認參數必須從右邊開始。
20,
第三章:
1,C++中class 的默認的做用域和private是同樣的。而struct的默認的是public同樣的。
2,inline在類裏面,若是在.h生成的就是內聯函數。若是是分開定義的,那麼就在.h定義這裏面加上inline字符就能夠了(注意cpp不要加。)
3,
成員函數+const 就是讓屬性值不要減小。 例如:GetValue() const{return this->a;} 這裏a不能有。
並且這裏面不可以調用non_const的成員函數。
4,若是函數返回類型採用const的話,那麼,只能賦值給一個const類型的局部變量。
5,
對象數組,當調用對象數組的時候,會默認調用每一個對象的構造函數。C ar[1000] 會調用1000次構造函數。若是沒有夠着函數,會默認生成一個默認的。
若是有了一個公有的,就不會生成默認的。
默認的夠着函數,裏面的類成員不能被初始化。
6,
拷貝構造函數:Person(Person& person)和Person(const Person& person),拷貝構造函數能夠有多個參數,可是這些參數必須有默認值。
當函數中有一個屬性指向了動態存儲空間的時候,應該調用拷貝構造函數。默認的只是直接賦值,這樣,兩個對象的指針就指向同一個對象了。若是命名了拷貝構造函數的話,就不會有默認的了。
這個時候,若是把這個拷貝構造函數放在私有,這樣就禁止了拷貝構造函數。
7,轉型構造函數,裏面要用到一個explicit。但是實現隱形轉換。
8,初始化夠着函數列表。Person():x(1),y(0),並且const只能經過這來初始化。
9,類靜態成員的聲明,int C::s = 0;並且若是沒有用static標明,不可以在函數中聲明。
10,const 對象不可以調用成員函數,主要是由於這樣可以改變這個類裏面的值。
第四章:
1,C++ 支持多重繼承,就是一個類能夠同時繼承多個類。
2,經過using能夠在子進程中改變基類的控制範圍。例如:
class BaseClass
{
public:
BaseClass(int value);
int GetValue();
void SetValue(int i );
private:
int value;
}
class derivedClass: public baseClass
{
public:
DerivedClass(int a ,int b):BaseClass(a),valueB(b);
void SetValue(int i);
private:
using baseClass::GetValue;
int valueB;
}
3,若是繼承以後新成員(成員函數,成員變量)名稱(只同名就能夠)和基類的同名,他將會覆蓋這個老成員函數。其實也無所謂隱藏,BaseClass::SetValue()和DerivedClass::SetValue()來區別的就好了。
4,在公有繼承的方式下,保護成員是可以被子類看到的。
5,構造函數和析構函數是不可以被繼承的。當派生類沒有本身的構造函數的時候,會直接調用父類的默認構造函數。若是沒有聲明,在調用本身的初始化構造函數的時候,調用父類的初始化構造函數。
例如上面的類:若是子類沒有構造函數而父類有,這樣的話,父類的構造函數必須有默認構造函數。其實就是說,若是要是顯示調用了基類的構造函數的話,就不須要了。若是要是沒有顯示,須要父類有一個默認構造函數,子類會調用。
6,析構函數的工做和構造函數的調用順序正好相反。並且,析構函數每一個類至多隻有一個。
7,類成員初始化的順序取決於他在被繼承時所說明的順序,並不是初始化隊列的順序。
8,多重繼承的時候,若是兩個基類有同名的函數,這樣的話就會發成衝突會出錯。
多繼承的構造函數順序,基類的構造函數先被調用,數據成員所在類的構造函數次之,最後指向派生類的構造函數。這個其實就是由於構造函數的時候先執行父類的,而後纔是屬性複製,而後纔是當前的構造函數。
9,虛基類,當多重繼承的時候。例如:
class C : D1,D2
{
}
class D1: B
{
}
class D2: B
{
}
class B
{
public: int x;
}
這個時候當生成C的時候,會生成兩個B class的副本(內存裏面是兩個B的對象),這個時候,若是 C.B::x = 2; 是有問題的,由於這個時候並未指明是哪一個B 的副本。並且,當你調用C.x的時候也有二意性。C.D1::x 和 C.D2::x不是一個值。可是,若是上面的全都是弄成虛基類。也就是以下:
class D1 : virtual B
class D2: virtual B
這個時候就只有一個副本了,C.B::x =2 只有一份,不會有歧義。C.x也是。還有虛基類的構造函數最早調用。
10,繼承分爲三種繼承:
公共繼承,公有的-》公有,私有的—》不可訪問,保護的-》保護
私有繼承,公有的-》私有,私有的—》不可訪問,保護的-》私有
保護繼承,公有的-》保護,私有的—》不可訪問,保護的-》保護
11,類型適應:派生類的對象,引用,指針均可以賦值給基類的。
第五章:
1,虛函數這個東西,須要在基類上面定義virual函數,子類若是不定義也能夠(不定義回去找同名的),定義更好。虛函數的主要目的在於動態綁定,若是不是虛函數,那就是對象是什麼就調用什麼,而若是是虛函數,就是調用真正的。若是在外面定義的函數,只須要在生命時候加上virtual就能夠了。
例如: Base a; Derive b;
a = b;
a.print(); 若是print是虛函數,調用的就是b.print,若是不是調用的是a.print。
如今有這麼一個例子:
Class Base{
void Act1(){Act2();}
void Act2(){cout<<"ori act2"<<endl;}
}
class Derive:public Base
{
void Act2(){cout<<"dest act2"<<endl;}
}
Derive b; b.Act1(); 輸出是?
ori act2
若是把Act2 變成虛函數,這個時候結果就是 dest act
這裏主要是由於這個時候this指針已經多態了,你能夠把this當作 Ori* source = new Derive();
2,析構函數能夠是virual的。只要加了virtual,派生類的就都不須要加了。vitual析構函數的做用是delete 子類的時候(可是這時候是動態綁定,內容是子類的,表表面是基類的),會調用子類的析構函數,以後還會調用父類的析構函數。若是要是沒有virtual,動態綁定的時候,對不會調用子類的析構函數。若是是其餘函數,若是派生來加上了virual就是說它如今也是虛函數,下面的人能夠覆蓋。
3,靜態成員函數不能夠是虛函數。
4,重載:就是同一個類,兩個不一樣樣簽名的函數。---》編譯綁定
覆蓋:基類子類,虛函數,兩個一樣簽名(不含返回值)的函數。---》動態綁定
隱藏:基類子類,不是虛函數,函數名字相同就行。 ---》編譯綁定
若是虛函數,若是不產生覆蓋(在只有函數名字相同的時候),就會產生隱藏。
5,純虛函數主要是的寫法是: virtual void open() = 0; 又純虛函數的類不可以產生對象。
6,在#include <typeInfo> 中typeId()
也就是typeid(對象,引用,指針) == typeid(類,引用,指針) 例如class A;... A a; if(typeid(a) = typeid(A)){cout<<"TRUE"<<endl;}
7,動態函數中調用虛函數,搜現實調用本身類實現的,若是本身類沒有實現,就調用基類的虛函數。不會調用其餘派生類的。
第六章
1,不能被重載的運算符:?: . * ::;除了=以外,其餘的均可以被派生類繼承。操做符重載不改變優先級和集合率。
2, 頂層操做符重載在定義的時候必須就不是相類成員同樣了。他就沒有默認的類對象當作參數。並且必須明確的指出來。
例如,C operator+(const C&c, const C& c2) 這個主要就是 Cresult = c + c2;
而且,對於頂部操做符重載,咱們須要用到一個自定義個類。若是要是沒有的話,區分不了。
這樣的操做都是順序的,例如:C operator[](Point& s , int i)就是 s[i]這個樣的一個東西。是有前後順序的。
對於二次型操做符,與使用類成員函數相比,只要定義了可轉型的構造函數,使用頂層函數進行重載是能夠不用在意左右兩邊的。若是用類的話,第一個參數必須是類對象。(噁心:()
3,友元函數其實很簡單,就是在一個類裏面的方法的前面加上friend,放在public,protect,private均可以,反正不是這個類的函數。這樣在外面定義的時候不須要加上friend,這個時候這個函數就可以訪問這個類的私有和protect的變量的。例如:
class A
{
public:
void Print();
friend void PrintOut();
friend B::PrintA();
friend C;
private:
int a;
}
class B
{
public:
void PrintA();
}
class C
{
public:
void PrintA()
{
cout<<a<<endl;
}
}
void B::PrintA()
{
cout<<a<<endl;
}
void PrintOut()
{
cout<<a<<endl;
}
如上面,友元能夠爲一個類,一個類的成員函數,一個頂層函數。可是,咱們只建議在頂層操做符的時候使用。
3,>>的操做符重載,這裏通常第一個參數通常都是istream的引用。返回的也是。
()函數操做符的重載,double operator()(double x,double y) const { return x*2 + y;} ,這個就是f(1.5,3.2);
counter operator ++(); 前綴操做符 counter operator++ (int); 後綴操做符,後面的int就是爲了代表是後綴操做符。
第七章
1,模板這東西實際上是編譯程序會根據函數調用的實際狀況把T所表明的類加載進去。因此,若是T出了問題編譯是不能經過的。
函數模板在應用的時候,不要用<>來制定類型,他會直接經過傳入的參數類型直接定義T的類型。例如:
template<class T>
T Sum(T a,T b)
{
return a + b;
}
void main()
{
int sum = Sum(1,3);
}
2, 模板這個東西的格式比較好玩,就是生命的時候呢,類用永遠和《T》不要緊,可是在定義的時候<T>必定要制定了。並且,在它用於當作做用域的時候也須要制定。這個函數就不是了,模板函數不須要指定。例如,
template<class T, int i>
class A
{
public:
T a;
T Get_a_Value();
}
template<class T,int i>
T A<T,int i>::Get_a_Value()
{}
void main()
{
A<int,5> a;
int i = a.a;
}
並且還有一點須要注意,就是當你聲明template的類時候,這個類的方法好像必須定義在.h文件當中。
3,這裏還有一個值得注意到地方,不一樣T的template類是徹底不一樣的兩個類,例如上面的A<int,3>和A<int 4>;A<double,1>和A<int,1>;不是一個類型,因此他們不可能擁有同一個基類,同一個靜態變量。而A<int,4>和A<int,4>的對象就是同樣的。
4,STL包括容器,算法,迭代器,函數對象,適配器,配置器。
5,迭代器就是一個封裝了的指針,指向一個容器的每一個數值。他重載了*符號,訪問他說指向的值。還有他重載了++運算法。能夠移動。
有向前迭代器和向後迭代器,向前就是++向前,而向後就是++向後移動。還有,他有const不const,若是是const代表不可以改變iterator的值。
6,list -> 雙向鏈表
vector -> 能夠伸縮的數組
deque -> 兩端進行有效插入刪除的數組。
set 不含重複值的集合
map 鍵值不能夠重複
multiset 容許重複值的set
multimap 容許重複鍵值的map
vector 適合在尾部插入刪除的操做,deque適合兩邊插入刪除的操做。
list不可以經過下標訪問。
7,stack,queue, priority_queue: stack,queue默認派省委deque;priority_queue默認爲vector
stack<char> s;默認 stack<char,vector<char>> s
8,bitset記錄二進制,bitset<8> bs --8位0 bitset<8> bs(9) --8位表示9
其餘積累:
1,C++中沒有finally,必須用try catch來搞定,或者用對象控制。
2,C++中最好不要用兩層的調用。例如:a.b.c.size();
3,類的參數初始化在.h文件中就行。
4,typeid 是<typeinfo> 命名空間的。 dynamic<t>這個T爲目的端的。typeid只對有virtual的虛類纔有做用。也就是 polymorphic class type。http://www.cplusplus.com/reference/std/typeinfo/type_info/
5,vector 中的=就是copy。
6, 在C++的.h引用中,用#ifndef classFlag; #define classFlag #endif的方法,這個防止類重複定義。
7,一個類的私有函數其實就是一個類的private,是針對於類而言的,並非針對於對象而言的。例如,拷貝構造函數中就能夠在當前的構造函數中,調用另外一個同一個類對象的私有成員變量。例如:
A(const A& a)
{
this.num = a.num; //num是A類的私有成員
}
8,函數中char * a = "helloworld" 這個字符串是放在堆裏面的。char a[] = "helloworld"是放在棧裏面的。
9,explict 是用來避免隱式轉換的。不少時候構造函數肯能會有隱式轉換功能。例如:
A(int a);
A a(0); a = 5; 其實就是 A temp(5); a = temp; ~temp();
若是不想隱式轉換,就必須用explicit。上面爲explicit A(int a)就能夠了。
http://wenku.baidu.com/view/2d94f7264b35eefdc8d3334d.html
10,extern 的做用:他能夠用於修飾變量和方法,它的主要做用是防止在一個.h文件中定義的一個對象,而在另外一個文件中須要用extern鏈接。若是沒有extern這個時候編譯會出錯誤。由於他們都是先編譯以後鏈接,若是編譯以後再鏈接,就會出現同名的錯誤。
例如:a.h: int a; b.h extern int a 這個時能夠的,方法也是,可是若是要是沒有extern 鏈接的時候就會衝突
extern 'C' 這個主要做用就是爲了讓C++引用C中的方法的變量,由於C++ 有的時候編譯的C是不同的。例如,C++有函數重載的概念,而C老是沒有的。因此int find(int a,int b)在C++ 編譯以後會是 _find_int_int(注意沒有考慮返回值),而C中的只有_find。這個時候若是不用extern,就會出現找不到函數的現象。
因此,須要在引用.h文件時候。extern 'C'{#include 'ac.h'},或者單獨定義函數。
10,函數指針int* (*function)(int a, int b).
11, int const* p 和const int* p是同樣的都是指向一個指向一個const int的指針,而int * const p纔是指針不會變化的那種。 const int* const p呢 ?
12,UTF-8 3bytes UTF-16 2bytes。
13,__thiscall __cdecl這兩個主要是標明當前這兩個方法的主要類型,thiscall是類的成員函數,他在應用函數指針會出現問題,由於thiscall的函數基本都是經過類以後找函數表實現的,它的內部機制和普通的函數指針有所不一樣。而cdecl是回調函數,這個有一點好處就是函數指針能夠直接引用。通常外圍函數,和類的靜態函數是cdecl的。這裏須要注意若是你須要應用thiscall,就須要用到mem_fun和mem_fun_ref這兩個STL類,他們的主要做用就是轉化的。詳細請看http://apps.hi.baidu.com/share/detail/4994454
14,C++存儲區中分爲堆,棧,靜態存儲區。通常常量是放在靜態存儲區裏面的。
15,動態連接庫是在進程啓動的時候加載的。
16,只有指針才能動態綁定,對象是不行的。