C 語言到 C++ 過度

mf1crystal發表於2018-01-05

C語言和C++ 的區別:
C語言存在很多的灰色地帶,沒有深思熟慮的設計過程,殘留量過多低階語言的特徵例如直接利用指標進行記憶體操作,C語言的目標就是高效。
C語言是程式導向程式設計設計:資料結構和演算法,
問題的存在 軟體可重用性差,軟體可維護性差,構建的軟體無法滿足使用者需求。

C++物件導向程式設計:由現實世界建立軟體模型;
特點:直接分析使用者需求中設計的各個實體,在程式碼中描述現實世界中的實體,在程式碼中關聯各個實體協同工作解決問題,
優勢:構建的軟體能夠適應使用者需求的不斷變化,直接利用程式導向方法的有事而避開起劣勢。
高效的物件導向的語言,並且能夠相容已經存在的程式碼。

C++對C的加強:
名稱空間:名稱空間將全句作用域分成不同的部分,不同名稱空間的識別符號可以同名而不會發生衝突,名稱空間可以巢狀,全域性作用域也叫做預設名稱空間。
名稱空間的定義:
/**
namespace 是C++中的關鍵字,用來定義一個名稱空間,語法格式為:
namespace name
{
變數
函式

}
name是名稱空間的名字,它裡面可以包含變數、函式、類、typedef、#define 等,最後由{ }包圍
**/
使用域解析符:
::是一個新符號,稱為域解析操作符,在C++中用來指明要使用的名稱空間。
NameSpaceA::a = 10; // 使用名稱空間 NameSpaceA中的變數a

// 全域性變數a
int a;

// 2.3、名稱空間之間命名衝突:使用域解析符解決衝突
// 和全域性空間變數命名衝突
int main3()
{
using namespace Name1;
using namespace Name2;

//  a = 10;   有歧義
Name1::a = 10;  

// 全域性的變數使用預設名稱空間的域解析符
::a = 20;

return 0;

}

簡單的C++程式:
// 包含C++的標頭檔案

// 使用名為std的名稱空間 using namespace std; int main() {
// printf (“hello world\n”);
// cout 標準輸出 往螢幕列印內容 相當於C語言的 printf
// << 左移操作符,在這裡它的功能被改造,代表資料流向
// << 代表資料從右端移到左端 右端是 “hello world”字串,左端是 cout 標準輸出
// 所以 cout << “hello world” 代表將內容列印到標準輸出
// endl 代表換行,相當於 C語言的 ‘\n’
// << 操作符可以連著使用
cout << “Hello World!” << endl;

return 0; }

將std直接宣告在所有函式外部,這樣雖然使用方便,但是中大型專案開發中是不被推薦的,這樣做怎家了命名衝突的風險,我推薦在函式內部宣告std;

// C語言中的變數都必須在作用域開始的位置定義!!
// C++中更強調語言的“實用性”,所有的變數都可以在需要使用時再定義。
for (int i = 0; i < 10; i++)
{
std::cout << i << std::endl;
}

register關鍵字的變化:
register關鍵字請求“編譯器”將區域性變數儲存於暫存器中
C語言中無法取得register變數地址
在C++中依然支援register關鍵字
1、C++編譯器有自己的優化方式,不使用register也可能做優化
2、C++中可以取得register變數的地址
C++編譯器發現程式中需要取register變數的地址時,register對變數的宣告變得無效。

變數檢測加強:

// 在C語言中重複定義多個全域性變數是合法的
// 這些同名的全域性變數最終都會被連結全域性資料區的同一個地址空間上
int g_a;
int g_a = 1;

struct型別加強
C語言的struct定義了一組變數的集合,C編譯器並不認為這是一種新的型別;
C++中的struct 是一個新型別定義宣告;

struct Student {
char name[20];
int age;
}
int main() {
// C語言中 struct 定義了一組資料的集合,而不是一種新的資料型別
// 所以在定義變數的時候需要在前面加上 struct 關鍵字進行修飾
// C++中 struct 定義了一種新的資料型別,可以直接用來定義變數
Student stu1 = {“xiaoming”, 10};

return 0; }

C++ 中所有變數和函式都必須要有型別;
C語言中函式的一些不好的使用方式:

// 1 函式可以沒有返回引數型別
f()
{
printf (“hello world\n”);
}
// 2 函式引數可以沒有資料型別
g(i)
{
return i;
}

// 1 函式可以沒有返回引數型別
f()
{
printf (“hello world\n”);
}

// 2 函式引數可以沒有資料型別
g(i)
{
return i;
}

int main() {
// 3 沒有引數的函式可以接收任意個引數
f(1,2,3,4,5);
g(12,15);
return 0; }
C++中的加強
在C語言中
intf();表示返回值是int,接受任意引數的函式;
int(void);表示返回值為int無參函式;
在C++中
int();和int(void)具有相同意義,都表示返回值為int的無參函式;C++更加強調型別,任意的程式元素都必須顯示指明型別

新增bool型別的關鍵字:
C++中的布林型別
C++在C語言的基本型別系統之上增加了bool
C++中的bool可取的值只有true和false
理論上bool只佔用一個位元組,
如果多個bool變數定義在一起,可能會各佔一個bit,這取決於編譯器的實現

true代表真值,編譯器內部用1來表示
false代表非真值,編譯器內部用0來表示

三目運算子的增強:
// C語言中表示式的結果 放在什麼地方? ==> 暫存器
// 1
// 表示式返回的是一個值,是一個數
// 在C++中,表示式返回的是變數本身

// 2 如何做到的
// 讓表示式返回一個記憶體空間..記憶體的首地址 指標
// 在C語言中如何實現C++的效果

// 3 本質
// C++編譯器自己做了取地址的操作

>

int main()
{
int a = 10;
int b = 20;

// C++中三目運算子返回的是變數本身,所以可以作為左值使用
(a > b ? a : b) = 90;

// 在C語言中讓三目運算子可以當左值使用,可以通過返回變數地址實現
*(a > b ? &a : &b) = 90;
printf ("%d, %d\n", a, b);

return 0; }

C語言返回變數的值C++語言返回的是變數本身;
C語言中的三目運算子返回的是變數值,不嫩作為左值使用
C++中的三目運算子可直接返回變數本身,因此可以出現在程式的任何地方

注意:三目運算子可能返回的值中如果有一個是常量值,則不能作為左值使用(a < b ? 1 : b )= 30;

C語言如何讓支援類似C++的特性呢?
當左值的條件:要有記憶體空間;C++編譯器幫助程式設計師取了一個地址而已

C++中的const
C和C++中的const比較
C語言中的const

int main() {
// C語言中 const修飾的變數是一個常變數,本質還是變數,有自己的地址空間
const int a = 10;
int p = (int )&a;

*p = 5;

printf ("%d\n", a);

return 0;
 }

C++中的const

int main() {
// C++中 const 變數宣告的是一個真正的常量,不是變數,所以編譯器不會為該常量分配空間
// const 修飾的常量會被放到 符號表 中
const int a = 10;

// 這裡對 const 常量取地址,這一步操作會讓編譯器為該變數分配空間,分配的空間並不會被 a 使用
int *p = (int *)&a;

// 通過指標改變指向的空間的值,這個空間是編譯器為常量分配的空間,但是常量的值並不在這個空間內
// 所以即使通過指標修改了這個空間的值,也不會影響到 a 本身
*p = 5;

// a 的值不變,因為它的值在符號表中,不在程式執行的空間內
printf ("%d, %p\n", a, *p);

return 0; }

C++編譯器對const常量的處理
當碰見常量宣告時,在符號表中放入常量 ==> 問題:那又如何解釋取地址
編譯過程中若發現對const使用了extern或者&操作符,則給對應的常量分配儲存空間(相容C)
但是編譯過程中若發現使用常量則直接以符號表中的值替換,即使給該常量分配了空間,也並不使用裡面的值

const和#define
不同之處:
對比加深
C++中的const常量類似於巨集定義
const int c = 5; ≈ #define c 5
C++中的const常量與巨集定義不同
const常量是由編譯器處理的,提供型別檢查和作用域檢查
巨集定義由前處理器處理,單純的文字替換
相同之處:

int main() {
const int a = 1;
const int b = 2;

int arr[a + b] = {1,2,3};
for (int i = 0; i < a+b; i++)
{
    printf ("%d\n", arr[i]);
}

return 0; }

C++中的const修飾的,是一個真正的常量,而不是C中變數(只讀)。在const修飾的常量編譯期間,就已經確定下來了

相關文章