C++對C的擴展、增強


C++對C的擴展

1. 雙冒號::作用域運算符

代碼中對同一個變量多次聲明,在代碼塊中使用時,局部變量會將全局變量隱藏。若在代碼塊使用變量前添加::,表示為全局變量。

::表示作用域運算符,如常見的std::cout,std::endl;等,表示cout和endl是std作用域下的標識符。

2. 命名空間namespace

主要用來解決命名沖突的問題,如多個人開發的不同模塊中使用了相同的變量名和函數名,fatal error LNK1169:找到一個或多個重定義的符號,這時可以使用命名空間,將不同的模塊分隔開。

1 namespace QGY{
2     int a;
3     void test();
4     struct QGYTEST{
5         int b;
6     };
7     class QGYNUM{};
8 }

使用命名空間的注意事項:(1)必須在全局作用域下聲明;(2)命名空間下可以放函數,變量、結構體和類;(3)命名空間可以嵌套命名空間;(4)命名空間是開放的,可以隨時加入新成員(添加時只需要再次聲明namespace,然后添加新成員即可,示例如下);(5)無名或匿名命名空間,相當於static變量;(6)可以對命名空間起別名(一般不用)

namespace QGY{
	int m ;
}

3. using聲明和using編譯指令

using QGY::a; //聲明
using namespace QGY; //編譯指令

對於聲明來說,如果局部范圍內還有a,會出現二義性,程序不知道使用哪一個,因此應避免這種情況.

1 void test01(){
2     int a = 10;
3     using QGY::a; //這里在聲明的時候不能進行賦值,可以在下一行,a = 20;
4     std::cout << a << std::endl;
5 }

這里程序會出現錯誤, error C2874: using 聲明導致“QGY::a”的多次聲明。

對於編譯指令,如果局部范圍還有a,會使用局部變量。如果還有另外的命名空間也聲明了a,且同時打開了其他空間,則也會出現二義性。

1 void test02(){
2     int a = 10;
3     using namespace QGY; //這里只是打開空間,並沒有指定使用
4     std::cout << a << std::endl;
5 }
1 void test03(){
2     using namespace QGY; //只是打開房間就可以訪問到a,打開多個房間就會產生二義性
3     std::cout << a << std::endl;
4 }

C++對C的增強

 1.全局變量檢測增強

C語言會忽略對全局變量重定義的檢測,但不會忽略對局部變量的檢測,C++中都會報錯:error C2086: “int a”: 重定義

//全局變量不會報錯
int a;
int a = 10;

//局部變量會報錯
void test(){
	int a;
	int a = 10;
}

2.函數檢測增強:包括函數形參類型檢測,形參數目檢測,函數返回值檢測,C都會忽略,C++不會

1 //C中函數形參沒有參數類型,沒有返回值,調用參數過多都會忽略
2 int test(m, n){
3 
4 }
5 
6 void test01(){
7     test(1,2,3);
8 }

 3.類型轉換檢測增強

C語言中malloc開辟內存空間時默認生成void*指針,可以轉換成任意指針,C++中則不行,必須顯式的進行強制轉換。

4.struct增強

(1)C中strcut中不能有函數,C++中可以有,並且與class的區別在於是否有私有成員,和是否有構造函數;

(2)通過如下方式聲明struct時,C語言定義使用結構體時必須使用struct,C++可以不用。

1 struct Person{
2     int a;
3 };
4 
5 struct Person myperson; //C
6 Person myperson; //C++

5.bool類型增強

C語言中沒有bool類型,C++中有bool類型,其中sizeof(bool)=1

6.三目運算符增強

 1 a > b?a : b; 

C語言中返回的是值,C++中返回的是變量,C語言中下面代碼會報錯:error C2106: “=”: 左操作數必須為左值,表明代碼中為20=100,所以會報錯。

1 void test01(){
2     int a = 10;
3     int b = 20;
4     printf("%d\n", a > b? a:b);
5     a > b ? a : b = 100; 
6 }

如果想改變三目運算符后的結果,可以按照如下代碼進行修改

 1 *(a > b? &a:&b) = 100; 

C++則不會,因為C++三目運算后為變量,因此可以進行賦值操作,其中a  = 10, b = 100;

1 void test01(){
2     int a = 10;
3     int b = 20;
4     a > b ? a : b = 100;
5     cout << a << " " << b << endl;
6 }

另外下面三種情況下的a和b的值是不同的

1 //a=100, b=20
2 (a < b ? a : b) = 100;
3 
4 //a=10, b=100
5 (a > b ? a : b) = 100;
6 
7 //a=10, b=20
8 a < b ? a : b = 100;

最后一種情況,不會執行b=100,其中帶括號的是按照我們的想法去執行代碼,不帶括號的話,優先級不同導致結果和預想的不同。

7.const增強

(1)是否可以修改

C語言中的全局const不可修改,是真常量,如果對其修改會出現訪問沖突,另外不可以聲明數組的大小(這是C的缺陷,也是為什么替代不了define);局部const為偽常量,可以進行修改,同時不可以用於聲明數組的大小(真假都不可以聲明數組的大小)。

1 const int m = 0; //全局靜態變量受到保護,不可修改
2 void test01(){
3     const int n = 1; //偽常量,可以通過地址進行修改
4     int *p = &n; //可以不加強制轉換
5     *p = 100;
6     printf("%d\n", n);
7 
8     int am[n]; //n不可用於聲明大小,不是常量值
9 }

C++不管全局還是局部都是真常量,不可修改,同時可以初始化數組,原因如下(取地址時會分配臨時內存):

(2)鏈接屬性

C語言的const默認是外部鏈接,C++默認是內部鏈接

1 //1.cpp
2 const int a = 10; 
3 
4 //2.cpp
5 extern const int a;

C語言中進行訪問時可以的,但C++中需要在1.cpp的聲明前加extern否則無法使用

(3)const分配內存

是否分配內存,我們可以根據const修飾的變量是否能夠修改來確定。

編譯器通常不為普通const常量分配存儲空間,而是將它們保存在符號表中,這使得它成為一個編譯期間的常量,沒有了存儲與讀內存的操作,使得它的效率也很高,但是在下列幾種情況下編譯器會為const定義的常量分配內存的。

(3.1)取地址時,const會分配臨時內存,不可以進行間接修改

1 void test003(){
2     const int m = 10;
3     int *p = (int *)&m;//分配臨時內存,不可以進行間接修改
4     *p = 100;
5     cout << m << endl;
6 }

(3.2)extern編譯器也會為變量分配內存

因為使用了extern,我們將可能在外部文件使用該變量,而const默認的是內部鏈接,所以我們必須要為之分配內存的。

(3.3)用普通變量初始化const變量,會分配內存

1 void test003(){
2     int m = 10;
3     const int b = (int *)&m; //分配內存,且可以跳過編譯器檢測進行間接修改,另外需要加強制轉換
4     int *p = &b;
5     *p = 100;
6 }

(3.4)自定義數據,加const也會分配內存

 1 struct Person{
 2     int age;
 3 };
 4 
 5 void test004(){
 6     const Person person = {10};//分配內存,且可以跳過編譯器檢測進行間接修改
 7     
 8     Person *b = (Person*)&person; 
 9     (*b).age = 20;
10     cout << (*b).age << endl;
11 }

 (4)盡量用const替換define

對於常量,盡量替換因為const有數據類型檢查和作用域。另外define用於宏定義時,可以用undef進行解除。但是對於有些條件編譯時需要define,則不能替換。

define是應用於預處理的,而const是在編譯的時候處理的。對於單純常量,使用const與enum代替宏,對於函數形式的宏,則使用inline與template替代。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM