概述
C++可以追溯到1979年,C++之父Bjarne Stroustrup在在使用C語言研發工作時發現C語言的不足,并想要將其改進,到1983年,Bjarne Stroustrup在C語言的基礎上添加了面向對象編程的特性,設計出了C++的雛形。
網址推薦
C++官方文檔(英文):cppreference.com
C++官方文檔(中文):C++ 參考手冊 - cppreference.com
C++函數查詢:Reference - C++ Reference
C++程序
C++兼容C的絕大多數語法,所以我們仍可以在C++文件中使用printf函數
#include <stdio.h> int main()
{printf("hello world");return 0;}
類似于C的#include <stdio.h>,C++中也有一個標準庫. 我們想要調用就要用:#include <iostream>,所以,嚴格來說用C++寫出的printf函數應該是這樣寫的:
?
#include<iostream>
using namespace std;//命名沖突->命名空間
int main()
{cout << "hello world" << endl;return 0;
}
接下來,我們一一講解代碼中的元素.
當需要多人完成一個項目時,若兩人用了相同的變量名,但變量的值卻不同該怎么辦?
namespace命名空間
? ? ? ? 1.定義命名空間,需要使?到namespace關鍵字,后?跟命名空間的名字,然后接?對{}即可{}中即為命名空間的成員。命名空間中可以定義變量/函數/類型等。
? ? ? ? 2.namespace本質是定義出?個域,這個域跟全局域各?獨?,不同的域可以定義同名變量,所以下?的rand不在沖突了。
? ? ? ? 3.C++中域有函數局部域,全局域,命名空間域,類域;域影響的是編譯時語法查找?個變量/函數/類型出處(聲明或定義)的邏輯,所有有了域隔離,名字沖突就解決了。局部域和全局域除了會影響編譯查找邏輯,還會影響變量的聲明周期,命名空間域和類域不影響變量聲明周期。
? ? ? ? 4.namespace只能定義在全局,當然他還可以嵌套定義。
? ? ? ? 5.項??程中多?件中定義的同名namespace會認為是?個namespace,不會沖突。
? ? ? ? 6.C++標準庫都放在?個叫std(standard)的命名空間中。
namespace的使用
如果寫出這樣的代碼:
int main(){int rand = 10;//編譯報錯:error C2365: “rand”: 重定義;以前的定義是“函數”printf("%p\n", rand);//查找是編譯進行的return 0;
}
會出現重定義報錯
所以我們使用命名空間:
//“ ::”域作用限定符,不寫即為先從全局開始查找,也可以寫具體的域
namespace Frenemy
{int rand = 10;
}
int main(){//編譯報錯:error C2365: “rand”: 重定義;以前的定義是“函數”printf("%d\n", Frenemy::rand);//查找是編譯進行的return 0;
}
其中“ ::”域作用限定符,不寫即為先從全局開始查找,也可以寫具體的域,并且命名空間必須寫在全局變量中.
而對于多個文件中的相同的命名空間,C++會直接將其合并.
若在一個項目中,已經使用了一次命名空間,但仍有兩人使用相同變量又該怎么辦呢?
namespace的嵌套調用
在同一個命名空間中,假如有兩人ab與xy,我們就可以使用嵌套定義:
namespace Frenemy
{namespace ab{int rand = 1;}namespace xy{int rand = 2;}
我們如果要使用命名空間的值,例如ab里的rand,則使用Frenemy::ab::rand即可
namespace的展開
全部展開:使用using Frenemy(namespace)?
部分展開(只展開一個變量):使用using Frenemy(namespace)::ab::rand.要使用時直接調用rand變量即可.
對于標準庫函數standard(簡稱std), 每次寫語句時都要使用std::cout<<a<<std::endl;較為麻煩,所以對于平時小練習可以將標準庫函數直接展開.
C++輸入輸出
????????<iostream> 是 Input Output Stream 的縮寫,是標準的輸?、輸出流庫,定義了標準的輸?、輸出對象。
????????
????????std::cin 是 istream 類的對象,它主要?向窄字符(narrow characters (of type char))的標準輸?流。
????????std::cout 是 ostream 類的對象,它主要?向窄字符的標準輸出流。
????????std::endl 是?個函數,流插?輸出時,相當于插??個換?字符加刷新緩沖區。
????????<<是流插?運算符,>>是流提取運算符。(C語?還?這兩個運算符做位運算左移/右移)
????????C++一行可以輸入輸出多個字符和字符串,并且可以自動識別多種類型
c語言中的printf在C++中就相當于輸出函數cout.
int main()
{printf("hello world!\n");cout << "hello world!" << endl;return 0;
}//這兩者是同一效果
缺省參數
????????缺省參數是聲明或定義函數時為函數的參數指定?個缺省值。在調?該函數時,如果沒有指定實參則采?該形參的缺省值,否則使?指定的實參,缺省參數分為全缺省和半缺省參數。(有些地?把缺省參數也叫默認參數)
????????帶缺省參數的函數調?,C++規定必須從左到右依次給實參,不能跳躍給實參。
????????函數聲明和定義分離時,缺省參數不能在函數聲明和定義中同時出現,規定必須函數聲明給缺省值。
全缺省參數
全部形參給缺省值,例如:
// 全缺省
void Func1(int a = 10, int b = 20, int c = 30)
{cout << "a = " << a << endl;cout << "b = " << b << endl;cout << "c = " << c << endl << endl;
}
要調用函數時就可以不用給形參,如果要給形參,則只能按順序從前往后給且不能跳著給.
半參省參數
// 半缺省
void Func2(int a, int b = 10, int c = 20)
{cout << "a = " << a << endl;cout << "b = " << b << endl;cout << "c = " << c << endl << endl;
}
半參省參數的規定是從右向左給形參賦值,也不能跳著給.
函數重載
????????C++?持在同?作?域中出現同名函數,但是要求這些同名函數的形參不同,可以是參數個數不同或者類型不同。這樣C++函數調?就表現出了多態?為,使?更靈活。C語?是不?持同?作?域中出現同名函數的。
參數類型不同
????????相同函數名的函數其形參類型不同則為函數重載,例如:
// 1、參數類型不同
int Add(int left, int right)
{cout << "int Add(int left, int right)" << endl;return left + right;
}double Add(double left, double right)
{cout << "double Add(double left, double right)" << endl;return left + right;
}
參數個數不同
? ? ? ? 相同函數名的函數其形參個數不同則為函數重載,例如:
// 2、參數個數不同
void f(int a, int b)
{cout << "f(int a, int b)" << endl;
}void f(int a)
{cout << "f(int a)" << endl;
}
參數類型順序不同?
????????相同函數名的函數其形參順序不同則為函數重載,例如
void f(int a, char b)
{cout << "f(int a,char b)" << endl;
}void f(char b, int a)
{cout << "f(char b, int a)" << endl;
}
注意?
? ? ? ? 1.需要注意的是,返回值不同并不能說明兩函數為函數重載,因為函數返回值可以不被調用;如果其中一個沒有返回值,而另一個有,當需要返回值時也無法區分 .
? ? ? ? 2.下列函數f()調用時會報錯,因為編譯器不知道執行哪一個!
// 下?兩個函數構成重載
// f()但是調?時,會報錯,存在歧義,編譯器不知道調?誰
void f1()
{cout << "f()" << endl;
}void f1(int a = 10)
{cout << "f(int a)" << endl;
}
引用
?????????引?不是新定義?個變量,?是給已存在變量取了?個別名,編譯器不會為引?變量開辟內存空間,它和它引?的變量共?同?塊內存空間。我們可以粗淺的將其理解為沒有開辟新空間的指針.
引用的特性
? ? ? ? 1.引?在定義時必須初始化
? ? ? ? 2.?個變量可以有多個引用
? ? ? ? 3.引??旦引??個實體,再不能引?其他實體
例如
int main()
{int a = 0;// 引?:b和c是a的別名,放在類型后面就是引用,別名相當于指針,但別名的地址與原變量相同int& b = a;int& c = a;// 也可以給別名b取別名,d相當于還是a的別名int& d = b;//這?取地址我們看到是?樣的++d;cout << &a << endl;cout << &b << endl;cout << &c << endl;cout << &d << endl;return 0;
}
相當于為變量取外號?.
例如我們熟悉的Swap函數,用指針寫是這樣:
void Swap(int* rx, int* ry)
{int tmp = *rx;*rx = *ry;*ry = tmp;
}
用引用寫是這樣:
void Swap(int& rx, int& ry)
{int tmp = rx;rx = ry;ry = tmp;
}
看起來確實簡潔一點, 這些就是引用的一些基礎知識。
總結
學會這幾個知識點,我們就可以理解開篇的那個函數代表了什么意思了。
C++中許多新語法的提出,其實也就是Bjarne Stroustrup對C語言一些語法的不滿并對其進行的改造。我們可以發現,這幾個知識點確實對應著C語言語法里一些較為不方便的地方。