C++對C語言的增強
C++對C語言加強
2. C++對C語言的加強
2.1 namespace名稱空間
2.1.1 C++名稱空間基本常識
所謂namespace,是指識別符號的各種可見範圍。C++標準程式庫中的所
有識別符號都被定義於一個名為std的namespace中。
一 :
在你的編譯器include資料夾裡面可以看到,二者是兩個檔案,開啟檔案就會
發現,裡面的程式碼是不一樣的。字尾為.h的標頭檔案c++標準已經明確提出不支
持了,早些的實現將標準庫功能定義在全域性空間裡,宣告在帶.h字尾的標頭檔案
裡,c++標準為了和C區別開,也為了正確使用名稱空間,規定標頭檔案不使用
字尾.h。 因此,
1)當使用<iostream.h>時,相當於在c中呼叫庫函式,使用的是全域性命
名空間,也就是早期的c++實現;
2)當使用
使用namespace std;這樣才能正確使用cout。
二: 由於namespace的概念,使用C++標準程式庫的任何識別符號時,可
以有三種選擇:
1)直接指定識別符號。例如std::ostream而不是ostream。完整語句如
下:
std::cout << std::hex << 3.4 << std::endl;
2)使用using關鍵字。
using std::cout;
using std::endl;
using std::cin;
以上程式可以寫成 :
cout << std::hex << 3.4 << endl;
3)最方便的就是使用using namespace std; 例如: using namespace std;
這樣名稱空間std內定義的所有識別符號都有效(曝光)。就好像它們被宣告
為全域性變數一樣。那麼以上語句可以如下寫: cout <<hex << 3.4 << endl;
因為標準庫非常的龐大,所以程式設計師在選擇的類的名稱或函式名 時就很有可能和標準庫中的某個名字相同。所以為了避免這種情況所造成的名字衝突,就把標 準庫中的一切都被放在名字空間std中。但這又會帶來了一個新問 題。無數原有的C++程式碼都依賴於使用了多年的偽標準庫中的功能,他們都是在全域性空間下的。所以就有了<iostream.h> 和
2.1.2 C++名稱空間定義以及使用方法
在C++中,名稱(name)可以是符號常量、變數、巨集、函式、結構、枚
舉、類和物件等等。為了避免,在大規模程式的設計中,以及在程式設計師使用各
種各樣的C++庫時,這些識別符號的命名發生衝突。
標準C++引入了關鍵字namespace(名稱空間/名字空間/名稱空間/名
域),可以更好地控制識別符號的作用域。
std是c++標準名稱空間,c++標準程式庫中的所有識別符號都被定義在std
中,比如標準庫中的類iostream、vector等都定義在該名稱空間中,使用時要
加上using宣告(using namespace std) 或using指示(如std::string、
std::vector
C中的名稱空間
在C語言中只有一個全域性作用域
C語言中所有的全域性識別符號共享同一個作用域
識別符號之間可能發生衝突
C++中的名稱空間
名稱空間將全域性作用域分成不同的部分
不同名稱空間中的識別符號可以同名而不會發生衝突
名稱空間可以相互巢狀
全域性作用域也叫預設名稱空間
C++名稱空間的定義:
namespace name {
…
}
C++名稱空間的使用:
使用整個名稱空間:using namespace name;
使用名稱空間中的變數:using namespace::variable;
使用預設名稱空間中的變數:namespace::variable
預設情況下可以直接使用默 認名稱空間中的所有識別符號
2.1.3 C++名稱空間程式設計實踐
#include <stdio.h>
namespace NameSpaceA
{
int a = 0;
}
namespace NameSpaceB
{
int a = 1;
namespace NameSpaceC
{
struct Teacher
{
char name[10];
int age;
};
}
}
int main(void)
{
using namespace NameSpaceA;
using NameSpaceB::NameSpaceC::Teacher;
printf("a = %d\n", a); //0
printf("a = %d\n", NameSpaceB::a);//1
NameSpaceB::NameSpaceC::Teacher t2;
Teacher t1 = {"aaa", 3};
printf("t1.name = %s\n", t1.name); //aaa
printf("t1.age = %d\n", t1.age);
//3
return 0;
}
2.1.4 結論
1) 當使用
namespace std;這樣才能正確使用cout。若不引入using namespace std ,需要這
樣做。std::cout。
2) c++標準為了和C區別開,也為了正確使用名稱空間,規定標頭檔案不使用
字尾.h。
3) C++名稱空間的定義: namespace name { … }
4) using namespace NameSpaceA;
5) namespce定義可巢狀。
2.2 “實用性”增強
#include <iostream>
using namespace std;
//C語⾔中的變數都必須在作⽤域開始的位置定義!!
//C++中更強調語⾔的“實⽤性”,所有的變數都可以在需要使⽤時再定義。
int main(void)
{
int i = 0;
cout << "i = " <<i <<endl;
int k;
k = 4;
cout << "k = " <<k <<endl;
return 0;
}
2.3 變數檢測增強
/*
在C語⾔中,重複定義多個同名的全域性變數是合法的
在C++中,不允許定義多個同名的全域性變數
C語⾔中多個同名的全域性變數最終會被連結到全域性資料區的同⼀個地址空間上
int g_var;
int g_var = 1;
C++直接拒絕這種⼆義性的做法。
*/
#include <iostream>
int g_var;
int g_var = 1;
int main(int argc, char *argv[])
{
printf("g_var = %d\n", g_var);
return 0;
}
2.4 struct 型別增器
/*
C語⾔的struct定義了⼀組變數的集合,C編譯器並不認為這是⼀種新的型別
C++中的struct是⼀個新型別的定義宣告
*/
#include <iostream>
struct Student
{
char name[100];
int age;
};
int main(int argc, char *argv[])
{
Student s1 = {"wang", 1};
Student s2 = {"wang2", 2};
return 0;
}
2.5 C++中所有變數和函式都必須有型別
/*
C++中所有的變數和函式都必須有型別
C語⾔中的預設型別在C++中是不合法的
函式f的返回值是什麼型別,引數⼜是什麼型別?
函式g可以接受多少個引數?
*/
//更換成.cpp試試
f(i)
{
printf("i = %d\n", i);
}
g()
{
return 5;
}
int main(int argc, char *argv[])
{
f(10);
printf("g() = %d\n", g(1, 2, 3, 4, 5));
getchar();
return 0;
}
在C語言中
int f( );表示返回值為int,接受任意引數的函式
int f(void);表示返回值為int的無參函式
在C++中
int f( );和int f(void)具有相同的意義,都表示返回值為int的無參函式
C++更加強調型別,任意的程式元素都必須顯示指明型別
2.6 新增bool型別關鍵字
/*
C++中的布林型別
C++在C語⾔的基本型別系統之上增加了bool
C++中的bool可取的值只有true和false
理論上bool只佔⽤⼀個位元組,
如果多個bool變數定義在⼀起,可能會各佔⼀個bit,這取決於編譯器的實現
true代表真值,編譯器內部⽤1來表⽰
false代表⾮真值,編譯器內部⽤0來表⽰
bool型別只有true(⾮0)和false(0)兩個值
C++編譯器會在賦值時將⾮0值轉換為true,0值轉換為false
*/
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
int a;
bool b = true;
printf("b = %d, sizeof(b) = %d\n", b, sizeof(b));
b = 4;
a = b;
printf("a = %d, b = %d\n", a, b);
b = -4;
a = b;
printf("a = %d, b = %d\n", a, b);
a = 10;
b = a;
printf("a = %d, b = %d\n", a,b);
b = 0;
printf("b = %d\n", b);
return 0;
}
2.7 三⽬運算子功能增強
#include <iostream>
using namespace std;
int main(void)
{
int a = 10;
int b = 20;
//返回⼀個最⼩數 並且給最⼩數賦值成30
//三⺫運算子是⼀個表示式 ,表示式不可能做左值
(a < b ? a : b ) = 30;
printf("a = %d, b = %d\n", a, b);
return 0;
}
1)C語言返回變數的值 C++語言是返回變數本身
C語言中的三目運算子返回的是變數值,不能作為左值使用
C++中的三目運算子可直接返回變數本身,因此可以出現在程式的任何地
方
2)注意:三目運算子可能返回的值中如果有一個是常量值,則不能作為左值
使用
(a < b ? 1 : b )= 30;
3)C語言如何支援類似C++的特性呢?
當左值的條件:要有記憶體空間;C++編譯器幫助程式設計師取了一個地址而已
2.8 const增強
2.8.1 const基礎知識
include
int main(void)
{
//const 定義常量---> const 意味只讀
const int a;
int const b;
//第⼀個第⼆個意思⼀樣 代表⼀個常整形數
const int *c;
//第三個 c是⼀個指向常整形數的指標(所指向的記憶體資料不能被修改,但是本⾝可以修改
int * const d;
//第四個 d 常指標(指標變數不能被修改,但是它所指向記憶體空間可以被修改)
const int * const e ;
//第五個 e⼀個指向常整形的常指標(指標和它所指向的記憶體空間,均不能被修改)
return 0;
}
合理的利用const的好處,
1指標做函式引數,可以有效的提高程式碼可讀性,減少bug;
2清楚的分清引數的輸入和輸出特性
int setTeacher_err( const Teacher *p)
Const修改形參的時候,在利用形參不能修改指標所向的記憶體空間
2.8.2 C語言中的“冒牌貨”
#include <stdio.h>
int main()
{
const int a = 10;
int *p = (int*)&a;
printf("a===>%d\n", a);
*p = 11;
printf("a===>%d\n", a);
return 0;
}
2.8.3 const 和 #define 的相同
#include <iostream>
//#define N 10
int main()
{
const int a = 1;
const int b = 2;
int array[a + b] = {0};
int i = 0;
for(i = 0; i < (a+b); i++)
{
printf("array[%d] = %d\n", i, array[i]);
}
return 0;
}
C++中的const修飾的,是一個真正的常量,而不是C中變數(只讀)。在
const修飾的常量編譯期間,就已經確定下來了
2.8.4 const 和 #define 的區別
#include <iostream>
void fun1()
{
#define a 10
const int b = 20;
}
void fun2()
{
printf("a = %d\n", a);
//printf("b = %d\n", b);
}
int main()
{
fun1();
fun2();
return 0;
}
C++中的const常量類似於巨集定義
const int c = 5 ≈#define c 5
C++中的const常量與巨集定義不同
const常量是由編譯器處理的,提供型別檢查和作用域檢查
巨集定義由前處理器處理,單純的文字替換
C語言中的const變數
C語言中const變數是隻讀變數,有自己的儲存空間
C++中的const常量
可能分配儲存空間,也可能不分配儲存空間
當const常量為全域性,並且需要在其它檔案中使用,會分配儲存空間
當使用&操作符,取const常量的地址時,會分配儲存空間
當const int &a = 10; const修飾引用時,也會分配儲存空間
2.9 真正的列舉
c 語言中列舉本質就是整型,列舉變數可以用任意整型賦值。而 c++中列舉
變數, 只能用被枚舉出來的元素初始化。
#include <iostream>
using namespace std;
enum season {SPR,SUM,AUT,WIN};
int main()
{
enum season s = SPR;
//s = 0; // error, 但是C語⾔可以通過
s = SUM;
cout << "s = " << s <<endl;
return 0;
//1