一文帶你初識C++和命名空間
1. 初識C++
C語言是結構化和模塊化的語言,適合處理較小規(guī)模的程序。對于復雜的問題,規(guī)模較大的程序,需要高度的抽象和建模時,C語言則不合適。為了解決軟件危機, 20世紀80年代, 計算機界提出了OOP(objectoriented programming:面向對象)思想,支持面向對象的程序設計語言應運而生。所以我們經常說到C++是面向對象的語言,而C語言是面向過程的語言。
1982年,Bjarne Stroustrup博士在C語言的基礎上引入并擴充了面向對象的概念,發(fā)明了一種新的程序語言。為了表達該語言與C語言的淵源關系,命名為C++。因此:C++是基于C語言而產生的,它既可以進行C語言的過程化程序設計,又可以進行以抽象數(shù)據(jù)類型為特點的基于對象的程序設計,還可以進行面向對象的程序設計。
請大家記住C++誕生的時間(1982年)以及發(fā)明C++的大佬 —— “本賈尼”!
2. C++的發(fā)展階段
作為了解就好,但是也要知道我們現(xiàn)在是在用C++版本是多少。
階段 | 內容 |
---|---|
C with classes | 類及派生類、公有和私有成員、類的構造和析構、友元、內聯(lián)函數(shù)、賦值運算符重載等 |
C++1.0 | 添加虛函數(shù)概念,函數(shù)和運算符重載,引用、常量等 |
C++2.0 | 更加完善支持面向對象,新增保護成員、多重繼承、對象的初始化、抽象類、靜態(tài)成員以及const成員函數(shù) |
C++3.0 | 進一步完善,引入模板,解決多重繼承產生的二義性問題和相應構造和析構的處理 |
C++98 | C++標準第一個版本,絕大多數(shù)編譯器都支持,得到了國際標準化組織(ISO)和美國標準化協(xié)會認可,以模板方式重寫C++標準庫,引入了STL(標準模板庫) |
C++03 | C++標準第二個版本,語言特性無大改變,主要:修訂錯誤、減少多異性 |
C++05 | C++標準委員會發(fā)布了一份計數(shù)報告(Technical Report,TR1),正式更名C++0x,即:計劃在本世紀第一個10年的某個時間發(fā)布 |
C++11 | 增加了許多特性,使得C++更像一種新語言,比如:正則表達式、基于范圍for循環(huán)、auto關鍵字、新容器、列表初始化、標準線程庫等 |
C++14 | 對C++11的擴展,主要是修復C++11中漏洞以及改進,比如:泛型的lambda表達式,auto的返回值類型推導,二進制字面常量等 |
C++17 | 在C++11上做了一些小幅改進,增加了19個新特性,比如:static_assert()的文本信息可選,F(xiàn)old表達式用于可變的模板,if和switch語句中的初始化器等 |
C++20 | 自C++11以來最大的發(fā)行版,引入了許多新的特性,比如:模塊(Modules)、協(xié)程(Coroutines)、范圍(Ranges)、概念(Constraints)等重大特性,還有對已有特性的更新:比如Lambda支持模板、范圍for支持初始化等 |
C++23 | 明確的對象參數(shù)(Deducing this)、if consteval、多維下標運算符、內建衰減復制支持、標記不可達代碼(std::unreachable)、平臺無關的假設([[assume]])、命名通用字符轉義、擴展基于范圍的 for 循環(huán)中臨時變量的生命周期、constexpr 增強、簡化的隱式移動、靜態(tài)運算符 static operator[] 以及類模板參數(shù)推導 |
C++還在不斷地向后發(fā)展。但是現(xiàn)在公司主流的是用的還是C++98和C++11,等大家以后工作時可以慢慢鉆研C++的新特性,現(xiàn)在這需要我們熟練的掌握C++98和C++11這兩個標準即可。
我們現(xiàn)在學習階段大都接觸到的也就是這兩種標準(C++11和C++98)。
2. 命名空間
2.1 為什么要有命名空間?
請大家看一下下面的代碼:
#include<stdio.h> int rand = 0; int main() { int rand = 10; printf("%d\n",rand); return 0; }
上面的代碼會不會報錯?相信掌握C語言語法的讀者就會說,上面的代碼是可以正常編譯通過的。沒錯,上面的代碼的確是沒有任何問題的。
那如果我將上述的代碼做了一點改變,代碼還能正常編譯過去嗎?
#include<stdio.h> #include<stdlib.h> int rand = 0; int main() { int rand = 10; printf("%d\n",rand); return 0; }
如果你們自己去測試的話,顯然會出現(xiàn)編譯錯誤。
這是什么原因呢?
編譯器說rand重定義,而且錯誤是我們在引用stdlib.h的頭文件之后才出現(xiàn)的。到這里我們就意識到了有個rand的變量名或者時函數(shù)名,而我們知道一個.c/.cpp的源文件在編譯階段的預處理階段會把頭文件的內容給展開,所以就會出現(xiàn)rand重定義了。
這個問題在C語言上只能是要你改變這個變量名了。C++就能夠解決這個問題,即使你不更改變量名,編譯器也不會報錯,這個C++的利器就是命名空間
為了讓大家對命名空間的這個新事物引起更高的重視,我來給大家舉個生活中實際例子:
比如現(xiàn)在有一個互聯(lián)網(wǎng)公司,這個公司最近準備研發(fā)一個項目,老板就把項目就分配給了一個小組,而小組里面有兩人小明和小剛負責分別負責這個項目的兩個模塊。他們兩個寫啊寫啊,終于有一天他們倆將各自寫的項目都提交了上去,編譯一下卻出現(xiàn)錯誤,經過檢查發(fā)現(xiàn)他們兩個項目的變量名有很多是重疊了,這個會出現(xiàn)命名沖突的問題。如果他們是用C語言來寫的話,那必定有一方得是改變變量命名,那兩個人肯定都不愿意改的。如果用C++的命名空間的話,就可以完美避開這個問題了。
好了,在講完命名空間的重要性之后,我們就得認識一下命名空間的用法以及底層的原理!
2.2 命名空間的語法
namespace 命名空間名 { 內容 }
下面我來一遍做展示,一遍拓展:
- 這個是我們進行正常的命名空間定義:
namespace test { int rand = 10; int Add(int x, int y) { return x+y; } struct Node { int data; struct Node* next; } }
??我們不僅可以在命名空間定義并初始化變量,還可以進行對函數(shù)的定義,結構體的定義等。
- 命名空間可以嵌套:
namespace N1 { int a; int b; int Add(int left, int right) { return left + right; } namespace N2 { int c; int d; int Sub(int left, int right) { return left - right; } } }
??可以看到我們中命名空間去嵌套另一個命名空間。
- 同一個工程中允許不同的文件出現(xiàn)名稱相同的命名空間,但是最后編譯器會將不同文件相同名稱的命名空間給合并到一起:
//這個是test.h文件里面的命名空間 namespace N1 { int Mul(int left, int right) { return left * right; } } //這個是test.cpp文件里面的命名空間 namespace N1 { int a; int b; int Add(int left, int right) { return left + right; } namespace N2 { int c; int d; int Sub(int left, int right) { return left - right; } } }
經過編譯器的編譯之后,最后的合并的結果就是:
namespace N1 { int Mul(int left, int right) { return left * right; } int a; int b; int Add(int left, int right) { return left + right; } namespace N2 { int c; int d; int Sub(int left, int right) { return left - right; } } }
2.3 命名空間的原理
提到命名空間,我們就不得不提另一個概念"域"。
想必大家或多或少都會在C語言中聽過"作用域"(全局域、局部域)這個名詞。這個就是"域"中的一種,在C++中還有命名空間域、類域等等。而我們現(xiàn)在說講的命名空間,它的實質就是一種命名空間域。
那可能有的讀者會問,"域"是個什么東西?
那我們可以先從我們熟悉的入手,全局域和局部域。我們都知道在給全局變量和局部變量去相同的變量名時,程序是不會報錯的,這個就是"域"的作用。我們可以把"域"想象成一面墻,被這面的墻隔開的事物互不干擾,你干你的事,我剛我的事。
講到這里,我相信你已經對命名空間域已經有感覺了。我們也可以把命名空間域看作是一面墻,將局部域與全局域給隔開了。在這個域里面有自己獨自維護的變量。
??所以我們可以總結一下:命名空間是解決全局變量與頭文件的命名沖突問題,或者是解決同一個工程項目中不同模塊之間的命名沖突問題。
2.4 使用命名空間的三種方式
我們講解了命名空間的原理,那命名空間里面的成員我們該怎么引用呢?比如:
namespace test { // 命名空間中可以定義變量/函數(shù)/類型 int a = 0; int b = 1; int Add(int left, int right) { return left + right; } struct Node { struct Node* next; int val; }; }
int main() { // 編譯報錯:error C2065: “a”: 未聲明的標識符 printf("%d\n", a); return 0; }
2.4.1 加命名空間名稱及作用域限定符( :: )
int main() { printf("%d\n", test::a); return 0; }
2.4.2 使用using關鍵字將命名空間中某個成員 引入
using test::b; int main() { printf("%d\n", test::a); printf("%d\n", b); return 0; }
這種方式建議使用?。。?/p>
2.4.3 使用using namespace 命名空間名 引入
using namespace test; int main() { printf("%d\n", test::a); printf("%d\n", b); Add(10,20); return 0; }
??注意:使用這個方法時是有風險的(這個命名空間里面有著和全局變量一樣的變量名),所以我們在平時進行練習或比賽的時候使用即可。
3. 簡單了解C++的輸入和輸出
我們再學一門新的語言時,往往會都會干一件事,就是在屏幕上輸出"Hello World"。
所以這里我們就簡單認識一下C++的輸入和輸出。
#include<iostream> // std是C++標準庫的命名空間名,C++將標準庫的定義實現(xiàn)都放到這個命名空間中 using namespace std; int main() { cout<<"Hello world!!!"<<endl; return 0; }
說明:
1. 使用cout標準輸出對象(控制臺)和cin標準輸入對象(鍵盤)時,必須包含< iostream >頭文件以及按命名空間使用方法使用std。
2. cout和cin是全局的流對象,endl是特殊的C++符號,表示換行輸出,他們都包含在包含< iostream >頭文件中。
3. <<是流插入運算符,>>是流提取運算符。
4. 使用C++輸入輸出更方便,不需要像printf/scanf輸入輸出時那樣,需要手動控制格式。
C++的輸入輸出可以自動識別變量類型。
5. 實際上cout和cin分別是ostream和istream類型的對象,>>和<<也涉及運算符重載等知識,這些知識我們我們后續(xù)才會學習,所以我們這里只是簡單學習他們的使用。
注意:早期標準庫將所有功能在全局域中實現(xiàn),聲明在.h后綴的頭文件中,使用時只需包含對應頭文件即可,后來將其實現(xiàn)在std命名空間下,為了和C頭文件區(qū)分,也為了正確使用命名空間,規(guī)定C++頭文件不帶.h;舊編譯器(vc 6.0)中還支持<iostream.h>格式,后續(xù)編譯器已不支持,因此推薦使用+std的方式。
#include <iostream> using namespace std; int main() { int a = 10; double b = 3.1415; char c = 'l'; // 可以自動識別變量的類型 cin>>a; cin>>b>>c; cout<<a<<endl; cout<<b<<" "<<c<<endl; return 0; }
??最后在聲明一點,std命名空間的使用慣例:
std是C++標準庫的命名空間,如何展開std使用更合理呢?在日常練習中,建議直接using namespace std即可,這樣就很方便。
using namespace std展開,標準庫就全部暴露出來了,如果我們定義跟庫重名的類型/對象/函數(shù),就存在沖突問題。該問題在日常練習中很少出現(xiàn),但是項目開發(fā)中代碼較多、規(guī)模大,就很容易出現(xiàn)。所以建議在項目開發(fā)中使用,像std::cout這樣使用時指定命名空間 + using std::cout展開常用的庫對象/類型等方式。
總結
到此這篇關于C++和命名空間的文章就介紹到這了,更多相關C++和命名空間內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
VisualStudio2022下配置 OpenMP多線程編程環(huán)境與運行
本文主要介紹了VisualStudio2022下配置 OpenMP多線程編程環(huán)境與運行,文中通過圖文介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2024-06-06C語言中判斷素數(shù)(求素數(shù))的思路與方法實例
計算機或者相關專業(yè)基本上大一新生開始學編程都會接觸的一個問題就是判斷質數(shù),下面這篇文章主要給大家介紹了關于C語言中判斷素數(shù)(求素數(shù))的思路與方法,需要的朋友可以參考下2022-03-03