C++基礎語法總結

這幾天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,只有指針才能動態綁定,對象是不行的。

相關文章
相關標籤/搜索