C++語言的發(fā)展簡史
- 將程序設(shè)計(jì)語言分為低級語言款筑、中級語言和高級語言。****機(jī)器語言和匯編語言屬于低級語言一類腾么,因?yàn)樗鼈兡軌蛑苯硬倏v計(jì)算機(jī)的寄存器和內(nèi)存奈梳。機(jī)器語言是一種依賴于CPU的指令系統(tǒng),使用機(jī)器指令的二進(jìn)制代碼編寫程序解虱,能夠直接被計(jì)算機(jī)識別攘须。匯編語言使用能夠代表指令的助記符來編寫程序,可以看作是符號化了的機(jī)器語言殴泰。
- 高級語言是面向用戶的語言于宙,很多語言在形式上接近于算術(shù)語言和自然語言,程序員編寫方便艰匙。使用高級語言編寫的程序易讀且通用性強(qiáng),但大部分不能直接與硬件打交道抹恳,也不能直接在計(jì)算機(jī)上運(yùn)行员凝,需要系統(tǒng)軟件的支持,如需要編譯程序和鏈接程序?qū)⒏呒壵Z言編譯鏈接為機(jī)器指令后才能運(yùn)行奋献。
- C語言是C++語言的前身健霹,在進(jìn)一步擴(kuò)充和完善C語言的基礎(chǔ)上得到了C++語言。
C++語言的特點(diǎn)
- 它是C語言的繼承瓶蚂,盡量兼容C語言糖埋,既保持了C語言的簡潔和高效,可以像C語言那樣進(jìn)行結(jié)構(gòu)化程序設(shè)計(jì)窃这,同時(shí)也增強(qiáng)了C語言對類型的處理瞳别。
- 加入了面向?qū)ο?/strong>的特征,可以進(jìn)行以抽象數(shù)據(jù)類型為特點(diǎn)的基于對象的程序設(shè)計(jì),還可以進(jìn)行以繼承和多態(tài)為特點(diǎn)的面向?qū)ο蟮某绦蛟O(shè)計(jì)祟敛。
與C語言相比疤坝,C++語言的優(yōu)點(diǎn):
- 從程序運(yùn)行的穩(wěn)定性來說,C++語言比C語言更安全馆铁,它支持過程化編程跑揉、面向?qū)ο缶幊毯头盒途幊獭R驗(yàn)槟軌蛑С置嫦驅(qū)ο蟮拈_發(fā)方式埠巨,所以C++語言的應(yīng)用領(lǐng)域更加廣泛历谍。
- C++語言可以運(yùn)行于多種平臺上,如Windows辣垒、MAC操作系統(tǒng)及UNIX等多種版本望侈。
- C++語言中加入了面向?qū)ο?/strong>的概念,雖然C語言的語法絕大多數(shù)被保留在C++語言中乍构,但C++的程序結(jié)構(gòu)和C語言的程序機(jī)構(gòu)存在很大差別甜无。
- C++語言對C語言做了很多改進(jìn),C++語言相對于C語言最根本的變化是引進(jìn)了類和對象的概念哥遮。
基本的輸入/輸出
功能 | C語言中使用函數(shù) | C++語言中提供類 | C++類中對象 | 運(yùn)算符 |
---|---|---|---|---|
鍵盤輸入 | scanf() |
輸入流類istream
|
cin |
>> |
屏幕輸出 | printf() |
輸出流類ostream
|
cout |
<< |
頭文件和命名空間
-
iostream
是C++的標(biāo)準(zhǔn)輸入/輸出流岂丘。當(dāng)在程序中使用cin
或cout
時(shí),必須在程序的最前面包含這個(gè)流眠饮。如果還要使用其他的內(nèi)容奥帘,那么需要包含其他的頭文件。每條#include
指令只可以包含一個(gè)頭文件仪召,如果需要包含多個(gè)頭文件寨蹋,則需要使用多條#include
嵌入指令。 - 在C++中扔茅,頭文件不再以
.h
結(jié)尾已旧,以.h
結(jié)尾的頭文件是C語言中常用的頭文件。
常用的頭文件有以下這些:
- 標(biāo)準(zhǔn)輸入/輸出流:
<iostream>
- 標(biāo)準(zhǔn)文件流:
<fstream>
- 標(biāo)準(zhǔn)字符串處理函數(shù):
<string>
- 標(biāo)準(zhǔn)數(shù)學(xué)函數(shù):
<cmath>
- 當(dāng)使用
<尖括號>
時(shí)召娜,C++編譯器將首先在C++系統(tǒng)設(shè)定的目錄中尋找要包含的文件运褪,如果沒有找到,再到指令中指定的目錄中去查找玖瘸。 - 當(dāng)使用
"雙引號"
時(shí)秸讹,C++編譯器在用戶當(dāng)前目錄下或指令中指定的目錄下尋找要包含的文件。
C++為了避免命名沖突雅倒,特別引入了“命名空間”的定義璃诀,即namespace
。命名空間的作用是為了消除同名引起的歧義蔑匣。
using namespace std;//使用命名空間
//定義如下
namespace 命名空間名
{
命名空間內(nèi)的各種聲明劣欢。棕诵。。氧秘。
(函數(shù)聲明年鸳、類聲明。丸相。搔确。)
}
強(qiáng)制類型轉(zhuǎn)換運(yùn)算符
static_cast
用于將一種數(shù)據(jù)類型轉(zhuǎn)換成另一種數(shù)據(jù)類型,使用格式如下:
//格式
static_cast<type>(expression)
void tranform() {
double d = 3.1415;
//下面四種寫法都是正確的
int a0 = static_cast<int>(d);//強(qiáng)制類型轉(zhuǎn)換
int a1 = int(d);//強(qiáng)制類型轉(zhuǎn)換運(yùn)算符的新形式
int a2 = (int)d;//強(qiáng)制類型轉(zhuǎn)換運(yùn)算符的舊形式
int a3 = d;//自動類型轉(zhuǎn)換
std::cout << "a0 = " << a0 << std::endl;//a0 = 3
std::cout << "a1 = " << a1 << std::endl;//a1 = 3
std::cout << "a2 = " << a2 << std::endl;//a2 = 3
std::cout << "a3 = " << a3 << std::endl;//a3 = 3
std::cout << "d = " << d << std::endl;//d = 3.1415
}
函數(shù)參數(shù)的默認(rèn)值
C++語言規(guī)定灭忠,提供默認(rèn)值時(shí)必須按從左至右的順序提供膳算,即有默認(rèn)值的形參必須在形參列表的最后。如果有某個(gè)形參沒有默認(rèn)值弛作,則它左側(cè)的所有形參都不能有默認(rèn)值涕蜂。
調(diào)用函數(shù)時(shí),主調(diào)函數(shù)的實(shí)參與被調(diào)函數(shù)的形參按從左至右的順序進(jìn)行匹配對應(yīng)映琳。
引用和函數(shù)參數(shù)的傳遞
1.引用的定義
引用相當(dāng)于給變量起了個(gè)別名机隙,變量對應(yīng)于某個(gè)內(nèi)存地址,如果給某個(gè)變量起了別名(不需要給它另開辟內(nèi)存單元)萨西,相當(dāng)于變量和這個(gè)引用都對應(yīng)到同一個(gè)地址有鹿。
程序中使用哪個(gè)名字都是允許的。在C++中引用的定義格式如下:
void refrensh() {
int a = 10;//在棧區(qū)分配一個(gè)變量a谎脯,并把常量區(qū)的10的地址賦值給變量a
int &b = a;//在棧區(qū)分配一個(gè)變量b葱跋,訪問變量b中所保存的地址,把a(bǔ)中保存的地址賦值給b
std::cout << &a << std::endl;//0x7ffeefbff52c
std::cout << &b << std::endl;//0x7ffeefbff52c
}
2.引用在函數(shù)中的使用
- 在程序中不僅能定義變量的引用源梭,還可以將引用用在函數(shù)中娱俺。引用既可以作為函數(shù)的參數(shù)使用,也可以作為函數(shù)的返回值使用废麻。
- 在C++中荠卷,函數(shù)調(diào)用時(shí)參數(shù)的傳遞有兩種:傳值和傳引用。
- 傳值烛愧,實(shí)際上是傳遞的對象的值油宜。
- 傳引用,是傳遞對象的首地址屑彻。
- 如果函數(shù)的形參不是引用验庙,那么調(diào)用時(shí)顶吮,實(shí)參傳遞給形參通常的方式是傳值的方式社牲,即將實(shí)參的值拷貝給形參。在函數(shù)執(zhí)行過程中悴了,都是對這個(gè)拷貝做操作的搏恤,函數(shù)執(zhí)行完畢返回后违寿,形參的值并不拷貝回實(shí)參,也就是說函數(shù)內(nèi)部對形參的修改不會影響到函數(shù)外部的實(shí)參的值熟空。
- 如果函數(shù)的形參是引用藤巢,則調(diào)用時(shí)實(shí)參傳遞給形參的是傳引用的方式。函數(shù)調(diào)用時(shí)息罗,實(shí)參對象名傳遞給形參對象名掂咒,形參對象名就成了實(shí)參對象名的別名,即形參是對應(yīng)實(shí)參的引用迈喉,它們是等價(jià)的绍刮,代表同一個(gè)對象,也可以看做是將實(shí)參的地址傳遞給了形參挨摸。在函數(shù)內(nèi)部對形參的操作孩革,都是對這個(gè)地址的內(nèi)容進(jìn)行的,相當(dāng)于對實(shí)參的值做了操作得运。所以膝蜈,當(dāng)函數(shù)執(zhí)行完畢返回后,實(shí)參的變化被保留下來熔掺。
#include <iostream>
void swapeValue(int a, int b) {
a = a ^ b;
b = a ^ b;
a = a ^ b;
std::cout << "swapeValue函數(shù)內(nèi):a = " << a << ", b = " << b << std::endl;
}
void swapeRef(int &a, int &b) {
a = a ^ b;
b = a ^ b;
a = a ^ b;
std::cout << "swapeRef函數(shù)內(nèi):a = " << a << ", b = " << b << std::endl;
}
int &refFunc(int &x) {
return x;
}
int main(int argc, const char * argv[]) {
int a = 10, b = 15;
swapeValue(a, b);
//swapeValue函數(shù)內(nèi):a = 15, b = 10
std::cout << "swapeValue函數(shù)外:a = " << a << ", b = " << b << std::endl;
//swapeValue函數(shù)外:a = 10, b = 15
swapeRef(a, b);
//swapeRef函數(shù)內(nèi):a = 15, b = 10
std::cout << "swapeRef函數(shù)外:a = " << a << ", b = " << b << std::endl;
//swapeRef函數(shù)外:a = 15, b = 10
int x = 30;
refFunc(x) = 35;//返回值是引用的函數(shù)調(diào)用表達(dá)式可以作為左值使用
std::cout << "返回值為引用:x = " << x << std::endl;
//返回值為引用:x = 35
return 0;
}
const與指針共同使用
const
修飾指針變量時(shí)饱搏,其基本含義如下:
-
如果唯一的
const
位于符號*
的左側(cè),表示指針?biāo)笖?shù)據(jù)是常量瞬女,數(shù)據(jù)不能通過本指針改變窍帝,但可以通過其他方式進(jìn)行修改;指針本身是變量诽偷,可以指向其他內(nèi)存單元坤学。void constFunc1() { int temp = 10; int temp1 = 20; //`const`位于`*`左側(cè),修飾`int *`類型报慕, //表示指針?biāo)笖?shù)據(jù)為常量 *a = &temp1;? //不能通過該指針修改數(shù)據(jù) const int *a = &temp; //指針本身是變量深浮,可以指向其他地址 a = &temp1; std::cout << "a = " << *a << std::endl;//a = 20 //也可以通過其他方式修改 temp1 = 11; std::cout << "a = " << *a << std::endl;//a = 11 }
-
如果唯一的
const
位于符號*
的右側(cè),表示指針本身是常量眠冈,不能讓該指針指向其他內(nèi)存地址飞苇;指針?biāo)赶虻臄?shù)據(jù)可以通過本指針就行修改。void constFunc2() { int temp = 10; int temp1 = 20; //`const`位于`*`右側(cè)蜗顽,修飾指針變量布卡, //表示指針本身為常量 int * const a = &temp; //該指針不能指向其他內(nèi)存地址 //a = &temp1; ? //指針?biāo)赶虻臄?shù)據(jù)可以通過本指針就行修改 *a = temp1; std::cout << "a = " << *a << std::endl;//a = 20 std::cout << "temp = " << temp << std::endl;//temp = 20 }
-
在符號
*
左右各有一個(gè)const
的時(shí)候,表示指針和指針?biāo)傅臄?shù)據(jù)都是常量雇盖,既不能讓指針指向其他地址忿等,也不能通過指針修改所指向的內(nèi)容。void constFunc3() { int temp = 10; int temp1 = 20; //指針和指針?biāo)傅臄?shù)據(jù)都是常量 const int * const a = &temp; //既不能讓指針指向其他地址 // a = &temp1; ? //也不能通過指針修改所指向的內(nèi)容 // *a = &temp1; ? }
簡單助記規(guī)則
const
修飾其左側(cè)內(nèi)容
如果const
是本行第一個(gè)標(biāo)識符崔挖,則修飾右側(cè)內(nèi)容
內(nèi)聯(lián)函數(shù)
- 為了避免這種頻繁的函數(shù)調(diào)用和返回贸街,c++語言引入了內(nèi)聯(lián)函數(shù)的概念庵寞。使用內(nèi)聯(lián)函數(shù),編譯器在編譯時(shí)并不生成函數(shù)調(diào)用薛匪,而是將程序中出現(xiàn)的每一個(gè)內(nèi)聯(lián)函數(shù)的調(diào)用表達(dá)式直接用該內(nèi)聯(lián)函數(shù)的函數(shù)體進(jìn)行替換捐川,就像整個(gè)函數(shù)體在被調(diào)用處被重寫了一遍一樣。很顯然逸尖,使用內(nèi)聯(lián)函數(shù)會使最終可執(zhí)行程序的體積增大古沥,這是以空間消耗節(jié)省時(shí)間開銷。
- 內(nèi)聯(lián)函數(shù)應(yīng)該定義在前娇跟,調(diào)用在后渐白,定義時(shí)只需在函數(shù)頭返回類型前面加上關(guān)鍵字
inline
。 - 內(nèi)聯(lián)函數(shù)主要用于代碼量少的函數(shù)逞频,頻繁調(diào)用纯衍。
- 如果函數(shù)體中有循環(huán)語句或
switch
語句,則通常不定義為內(nèi)聯(lián)函數(shù)苗胀。
函數(shù)的重載
所謂函數(shù)重載忠寻,是指在程序的同一范圍內(nèi)聲明幾個(gè)功能類似的同名函數(shù)潘懊。
實(shí)現(xiàn)函數(shù)重載必須滿足下列條件之一:
- 參數(shù)表中對應(yīng)的參數(shù)類型不同
- 參數(shù)表中參數(shù)個(gè)數(shù)不同
如果函數(shù)參數(shù)表中不同類型參數(shù)的次序不同借帘,也符合上面所說的條件剑按。要注意的是,返回值類型不能用來區(qū)分函數(shù)澜驮,也就是說陷揪,如果兩個(gè)函數(shù)的名字和參數(shù)表都是一樣的,僅僅返回值類型不同杂穷,則這兩個(gè)函數(shù)不是重載的悍缠,編譯器認(rèn)為它們是重復(fù)定義,會編譯報(bào)錯(cuò)耐量。
編譯階段飞蚓,程序還沒有執(zhí)行,所以并不知道返回值是什么廊蜒,更加確定不了它的類型趴拧,所以編譯器不能根據(jù)返回值來判斷該調(diào)用哪個(gè)函數(shù)。
int maxFunc(int a, int b) {
return a > b ? a : b;
}
float maxFunc(float a, float b) {
return a > b ? a : b;
}
double maxFunc(double a, double b) {
return a > b ? a : b;
}
采用引用參數(shù)山叮,也不能區(qū)分函數(shù)
//錯(cuò)誤的重載函數(shù)?
void log(double);
void log(double&)
二義性
//產(chǎn)生二義性?
int sun(int a, int b, int c = 0) {
return a + b + c;
}
int sun(int a, int b) {
return a + b;
}
指針和動態(tài)內(nèi)存分配
使用new
運(yùn)算符動態(tài)申請的內(nèi)存空間著榴,需要在使用完畢時(shí)釋放。C++提供了delete
運(yùn)算符屁倔,用來釋放動態(tài)分配的內(nèi)存空間脑又。delete
運(yùn)算符基本用法如下:
delete 指針;//釋放動態(tài)分配的內(nèi)存空間
delete [] 數(shù)組指針;//釋放數(shù)組
delete
運(yùn)算符后面的指針必須是指向動態(tài)分配的內(nèi)存空間的,否則運(yùn)行時(shí)和可能出錯(cuò)。
用string
對象處理字符串
c++
標(biāo)準(zhǔn)模板庫中提供了string
數(shù)據(jù)類型挂谍,專門用于處理字符串。string
是個(gè)類瞎饲,這個(gè)類型的變量稱為string對象
口叙。
1.string
對象的聲明
要在程序中使用string
對象,必須在程序中包含頭文件string
嗅战,即在程序的最前面加上如下語句:
#include <string>
聲明一個(gè)string
對象妄田,和聲明普通變量是類似的,格式如下:
string 變量名;
void declareString() {
//聲明string對象str驮捍,值為空
std::string str;
//聲明string對象city疟呐,并使用字符串常量進(jìn)行初始化
std::string city = "YangCheng";
//聲明string對象str2,并使用字符串變量進(jìn)行初始化
std::string str2 = city;
//使用字符串?dāng)?shù)組對string對象初始化
char name[] = "C++程序";
std::string pName = name;
//聲明一個(gè)string對象數(shù)組
std::string strArr[] = {
"beijing",
"Shanghai",
"shenzhen",
"guangzhou"
};
}
2.string
對象的操作
字符串賦值东且、取值启具、比較、拼接
void stringOpt1() {
std::string s1, s2;
s1 = "C++程序";
s2 = s1;
std::string s3;
std::cout << "s3 = " << s3 << std::endl;
//輸出:s3 =
s3 = s1 + s2;
std::cout << s1 + s2 << std::endl;
//輸出:C++程序C++程序
std::cout << "s3 = " << s3 << std::endl;
//輸出:s3 = C++程序C++程序
s3 += "de";
std::cout << "s3 = " << s3 << std::endl;
//輸出:s3 = C++程序C++程序de
bool b = s1 < s3;
std::cout << "bool = " << b << std::endl;
//輸出:bool = 1
char c = s1[2];
std::cout << "c = " << c << std::endl;
//輸出:c = +
std::cout << "s1[2] = " << s1[2] << std::endl;
//輸出:s1[2] = +
char arrStr[] = "hello";
s3 = s1 + arrStr;
std::cout << "s3 = " << s3 << std::endl;
//輸出:s3 = C++程序hello
}
字符串獲取長度珊泳、判空鲁冯、拼接、獲取容量色查、截取薯演、插入
void stringOpt2() {
std::string str;
if (str.empty()) {
std::cout << "str is null, " << "length = " << str.length() << std::endl;
//輸出:str is null, length = 0
} else {
std::cout << "str is not null" << std::endl;
}
str = str.append("abcdefg");
std::cout << "str = " << str << ", size = " << str.size() << std::endl;
//輸出:str = abcdefg, size = 7
const char *p = str.c_str();
std::cout << "p = " << p << std::endl;
//輸出:p = abcdefg
//查找字符串“de”,從第n個(gè)下標(biāo)開始
std::cout << "find: " << str.find("de", 0) << std::endl;
//輸出:find: 3
std::cout << "find: " << str.find("de", 4) << std::endl;
//輸出:find: 18446744073709551615
//查找失敗
//從第n個(gè)下標(biāo)開始插入字符串“123”
std::string str1 = str.insert(4, "123");
std::cout << "str1 = " << str1 << std::endl;
//輸出:str1 = abcd123efg
}
C++語言的程序結(jié)構(gòu)
C++程序以.cpp
作為文件擴(kuò)展名秧了,文件中包含若干個(gè)類和若干個(gè)函數(shù)跨扮。程序中必須有且僅有一個(gè)主函數(shù)main(),這是程序執(zhí)行的總?cè)肟谘檎薄V骱瘮?shù)也稱為主程序衡创。程序從主函數(shù)main()的開始處執(zhí)行,主函數(shù)可以在任何地方出現(xiàn)晶通,按照其控制結(jié)構(gòu)钧汹,一直執(zhí)行到結(jié)束。
程序的結(jié)束通常是遇到了以下兩種情形之一:
- 在主函數(shù)中遇到
return
語句录择。 - 執(zhí)行到主函數(shù)最后面的括號拔莱。
主函數(shù)中可以調(diào)用程序中定義的其他函數(shù),但其他函數(shù)不能調(diào)用主函數(shù)隘竭。主函數(shù)僅是系統(tǒng)為執(zhí)行程序時(shí)所調(diào)用的塘秦。
C++程序中,仍沿用C語言的注釋風(fēng)格动看,即注釋有以下兩種形式:
- 從
/*開始尊剔,到*/結(jié)束
,這之間的所有內(nèi)容都視作注釋菱皆。 - 從
//直到行尾
须误,都是注釋挨稿。