@TOC


📝C++簡述

C語言一樣,C++也是在貝爾實驗室誕生的,Bjarne Stroustrup於1979年首次推出,C++是一種高級編程語言,它是在C語言的基礎上發展而來,融合了面向對象的思想。它的特點是高效、低級和麪向對象。 在C++的發展歷程中,最為重要的里程碑是C++11標準的發佈。C++11版本增加了許多現代化的特性,例如類型推斷、lambdas表達式、移動語義、多線程支持等,大大提高了C++的編程效率和效果。

C++被廣泛應用於遊戲開發、圖形圖像處理、嵌入式系統等領域。例如騰訊公司就廣泛使用C++來開發遊戲引擎、QQ客户端等產品。C++也是Linux內核和Windows系統的主要實現語言。

在編程界,C++已經有40多年的歷史,儘管時代不斷變遷,但C++依然是系統級和高性能領域的首選語言之一。它在各大編程語言排行榜上長期位居前茅,被眾多科技巨頭廣泛應用。

C++融合了3種不同的編程方式:

  • C語言代表的過程性語言
  • C++在C語言基礎上添加的類代表的面嚮對象語言。
  • C++模板支持的泛型編程。

C++和C語言關係是啥呢?

C++語言是在C語言基礎上,添加了面向對象,模板等現代程序設計語言的特性而發展起來的。兩者無論是從語法規則上,還是從運算符的數量和使用上,都非常相似,所以我們常常將這兩門語言統稱為“C/C++”。

注意:C語言C++並不是對立的競爭關係: C++是C語言的加強,是一種更好的C語言。 C++是以C語言為基礎的,並且完全兼容C語言的特性。

C++標準

這裏是關於C++程序可移植性的標準:

一、是否需要修改代碼

如果一個C++程序滿足以下條件,則在重新編譯後可以在新平台直接運行,無需修改源代碼:

  1. 程序只調用標準C++語言元素和標準庫功能,不依賴任何特定平台的庫或API
  2. 程序不直接訪問硬件,不依賴特定的指令集或CPU架構。
  3. 程序遵循當前ISO標準的C++語言規範和標準庫定義。

二、實現可移植性的兩個關鍵點

  1. 硬件依賴性:如果程序直接訪問硬件或依賴特定的指令集,則不具有良好的移植性。
  2. 語言實現的一致性:不同平台下編譯器對C++標準的實現應保持一致,以確保可移植性。

三、C++標準的制定與發展

  1. ANSI和ISO聯合委員會從1990年開始制定統一的C++標準。
  2. 最早的標準ISO/IEC 14882:1998為C++奠定了基礎。
  3. 後續標準不斷修訂和增強語言功能,但保持向下兼容。
  4. 標準庫提供跨平台的接口,有助於提高程序的可移植性。
  5. 如果遵循標準,理論上程序可以在任何支持該標準的平台上通過重新編譯直接運行。

以上就是關於C++程序可移植性的一些基本標準和原則。如果滿足這些條件,則可以實現跨平台良好的可移植性。

如果你想了解C++標準有關版本,可以看看以下:

  • C++98標準:發佈於1998年,這是C++語言的第一個正式標準版本。
  • C++03標準:發佈於2003年,主要是對C++98標準的一些細微修改和補充。
  • C++11標準:發佈於2011年,這是一個重要的標準版本,增加了許多新的語言特性,如auto類型推導、lambda表達式、智能指針等。
  • C++14標準:發佈於2014年,基於C++11標準進行了一些增強,如常量表達式、二進制字面量等。
  • C++17標準:發佈於2017年,主要新增了模塊化支持、 paralle programming支持等新特性。
  • C++20標準:發佈於2020年,主要新增了範圍for循環、概括模板、可變參數模板等功能。 ....

🌠C++應用

騰訊超級喜歡C++開發? 作為互聯網巨頭之一的騰訊,一向都是眾多遊戲公司和科技企業的風向標

騰訊的歷史原因 1998年,騰訊成立之初主要開發BBS論壇系統,當時常用的開發語言有PHPASP等腳本語言以及C/C++兩種編程語言。由於需要開發遊戲等產品,出於性能考慮,騰訊最初選擇了C/C++來開發。

隨着業務的擴展,騰訊遊戲業務迅速發展,需要支持3D圖形等遊戲引擎,這就決定了必須選擇C/C++這種低級語言來開發。從此,C/C++成為騰訊主打的技術方向。

騰訊發展的必然選擇 經過20多年的發展,騰訊遊戲和IT技術團隊已經有數以萬計的C/C++開發人員,在遊戲引擎和系統開發等領域有着非常深厚的技術積累。

目前騰訊的QQ客户端、微信公眾號平台等核心產品都是基於C/C++技術研發的。從遊戲引擎、多媒體處理到操作系統開發,C/C++作為系統級語言的優勢很明顯。因此,C/C++成為騰訊不二選擇。

🌠C++語言優點

C++有8大特性,也就是它的8大優點:

⽂件使⽤⽅式

含義

跨平台/可移植性

跨平台是C++語言的核心優勢,在設計之初C++就很注重可移植性和跨平台性,因為C++的運行不依賴任何虛擬機,編譯生成的可執行文件可以直接在任何支持該平台的操作系統上運行,省去了大量的代碼重複編寫時間。

安全性

C++提供了面向對象、模板和異常等機制,可以有效避免資源泄漏和錯誤的訪問,使程序更安全可靠。

面向對象

C++是完全的面嚮對象語言,非常適合大型軟件的設計和開發。

簡單性

C++比C語言增加了更多面向對象的特性,如類、繼承、重載等,在保留C語言簡單易用的同時提高了程序的可維護性。

高性能

C++的性能一直處於領先地位,尤其是在遊戲、圖形和嵌入式系統等領域。

分佈式

C++支持網絡編程和遠程調用,可以開發分佈式系統。

多線程

C++11標準增加了多線程支持,可以方便高效地開發多線程程序。

健壯性

C++提供智能指針、異常處理等機制,減少內存泄漏和崩潰的可能性,使程序更健壯可靠。

第一個C++程序

#include <iostream>
using namespace std;//使用std命名空間
int main(int argc , char *argv[])
{
    int a;
    a=10;
    cout <<"a:" <<a<<endl;
    cout << "Hello, World!" << endl;
    return 0;
}

C++拓展及命名空間的使用_命名空間

輸出:

C++拓展及命名空間的使用_作用域_02

注意: 1️⃣、在C語言中,頭文件使用擴展名.h,作為一種簡單的通過名稱標識文件類型的方式。然而,C++的用法有所改變,C++頭文件不使用擴展名。有些C語言的頭文件被轉換為C++頭文件,這些文件被重新命名,去掉了.h擴展名(轉為C++風格頭文件),並在文件名前加上前綴c(表示來自C語言)。例如,C++版本的math.h變為cmathstdio.h變為cstdiostdlib.h變為cstdlib

2️⃣、命名空間是指標識符的各種可見範圍。使用關鍵字namespace來定義命名空間。命名空間是C++的一種機制,用於將具有邏輯關聯的大量程序實體組合在一起,這些實體共享相同的標識符。std是命名空間(名字空間)的名稱,命名空間的主要作用是解決日益嚴重的名稱衝突問題。隨着可重用代碼的增加,不同代碼庫中同名標識符之間的衝突會顯著增加。解決方法是將不同的代碼庫放置在不同的命名空間中。思考:如果在項目中需要定義兩個名為func的函數,並且這兩個函數都可以被其他文件訪問,應該怎麼辦?

答:如果在同一個項目中需要定義兩個同名函數func,而這兩個函數都需要被其他文件訪問,可以採取以下方法:

  1. 使用命名空間

可以把兩個func函數放入不同的命名空間中,比如:

namespace space1 
{
  void func() {
    // func定義1
  }
}

namespace space2 
{
  void func() {
   // func定義2 
  }
}

然後其他文件使用時加上命名空間前綴區分,如space1::func()space2::func()

  1. 使用函數重載

可以給兩個func函數添加不同的參數列表進行函數重載:

void func() 
{
  // func定義1
}

void func(int x) 
{
  // func定義2
}
  1. 將函數定義放在不同的頭文件中

比如func1.hfunc2.h,然後分別#include相應的頭文件。

  1. 使用類

可以將兩個func函數定義在不同的類中:

class A 
{
public:
  void func() {/*func1定義*/} 
};

class B 
{
public:
  void func() {/*func2定義*/}
};

總之,通過命名空間,函數重載,不同頭文件以及類等機制可以很好地區分開兩個同名函數。3️⃣、coutC++中的標準輸出流,endl用於輸出換行並刷新緩衝區。

🌠命名空間

C++命名空間的基本概念:

  1. 在大型項目開發中,會涉及大量名稱(如常量、變量、函數、類等),名稱管理是程序設計的基本活動之一。C++通過命名空間的機制,可以控制名稱的產生和訪問範圍。
  2. C++中所有名稱,如符號常量、變量、宏、函數、結構、枚舉、類以及對象等都是可以定義在命名空間中的。
  3. std命名空間是C++標準命名空間。C++標準庫中的所有標識符如iostream類和vector類都是定義在這個std命名空間中的。如果需要使用這些標準庫中的功能,需要添加using聲明或使用std前綴來限定名稱,比如使用std::cout輸出。

🌠命名空間的使用

命名空間的定義

C++中的命名空間是一種封裝標識符(如變量名、函數名、類名等)的方式,用於防止命名衝突。命名空間允許組織代碼以避免可能出現的標識符衝突,尤其是在大型項目或者在使用多個庫時。它可以被視為一種定義標識符的作用域,這些標識符在該命名空間內是可見的,而在命名空間外則不是。

定義命名空間的基本語法如下:

namespace 名稱 {
    // 定義變量、函數、類等
}

這裏,名稱是你給命名空間指定的名字,可以根據需要在裏面定義變量、函數、類等。

例如,定義一個名為myNamespace的命名空間,並在其中定義一個函數和一個變量:

namespace myNamespace 
{
    int myVariable = 0;
    void myFunction() 
    {
        // 函數實現
    }
}

使用命名空間內的成員時,需要使用命名空間的名稱和作用域解析運算符::來指定,如myNamespace::myVariablemyNamespace::myFunction()

命名空間可以嵌套定義,即一個命名空間內可以定義另一個命名空間。此外,C++還支持匿名命名空間和內聯命名空間的概念。匿名命名空間是在文件內部提供了一個獨一無二的命名空間,而內聯命名空間則允許在外層命名空間直接訪問內聯命名空間中的成員,無需通過作用域解析運算符。

ok來舉個例子:

#include <iostream>

// 外層命名空間
namespace outerNamespace {
    int outerVar = 10;

    // 嵌套命名空間
    namespace nestedNamespace {
        void nestedFunction() {
            std::cout << "Inside nestedFunction" << std::endl;
        }
    }

    // 內聯命名空間
    inline namespace inlineNamespace {
        void inlineFunction() {
            std::cout << "Inside inlineFunction" << std::endl;
        }
    }
}

// 匿名命名空間
namespace {
    void anonymousFunction() {
        std::cout << "Inside anonymousFunction" << std::endl;
    }
}

int main() {
    // 訪問外層命名空間變量
    std::cout << "outerVar: " << outerNamespace::outerVar << std::endl;
    
    // 訪問嵌套命名空間的函數
    outerNamespace::nestedNamespace::nestedFunction();
    
    // 由於inlineFunction在內聯命名空間中,可以直接通過外層命名空間訪問
    outerNamespace::inlineFunction();
    
    // 直接訪問匿名命名空間中的函數
    anonymousFunction();

    return 0;
}

每個對應輸出:

C++拓展及命名空間的使用_作用域_03

解析:在這個例子中,我們定義了一個外層命名空間outerNamespace,它包含一個變量outerVar、一個嵌套命名空間nestedNamespace和一個內聯命名空間inlineNamespacenestedNamespace內定義了一個函數nestedFunction(),而inlineNamespace內定義了一個函數inlineFunction()。因為inlineFunction()在內聯命名空間中,它可以被當作是直接在outerNamespace中定義的,所以我們可以不通過內聯命名空間的名稱直接訪問它。

此外,我們還定義了一個匿名命名空間,並在其中定義了函數anonymousFunction()。由於匿名命名空間的特性,該函數只在定義它的文件內部可見,從而提供了一種限制訪問範圍的方法。

注意

  • 命名空間的名字可以重複,這種重複並非兩個不同的命名空間,而是在編譯過程中將相同名字的命名空間合併,事實上還是一個命名空間
  • 命名空間不能在類和函數中定義

C++的using指令或using聲明可以用來簡化命名空間成員的訪問,但過度使用可能會引起名稱衝突的問題。

🌠怎麼使用命名空間中的內容呢?

在C++中,使用命名空間中的內容主要有以下幾種方式:

1. 直接使用完全限定名

這是最直接的方式,通過命名空間的名稱和作用域解析運算符::來訪問命名空間中的變量、函數或類型。例如:

#include <iostream>
namespace MyNamespace {
    void myFunction() {
        // 函數實現
        std::cout<<"void myFunction()"<<std::endl;
    }
    int myVariable = 42;
}

使用完全限定名來訪問:

int main() 
{
    MyNamespace::myFunction(); // 調用函數
    int value = MyNamespace::myVariable; // 訪問變量
    std::cout<<value<<std::endl;
    return 0;
}

輸出:

C++拓展及命名空間的使用_作用域_04

2. 使用using聲明

你可以使用using聲明來引入命名空間中特定的名稱,從而在當前作用域中直接使用這個名稱,而不需要每次都提供完整的命名空間前綴。例如:

using MyNamespace::myFunction;
using MyNamespace::myVariable;

int main() {
    myFunction(); // 現在可以直接調用函數,無需命名空間前綴
    int value = myVariable; // 直接訪問變量
    std::cout<<value<<std::endl;
    return 0;
}

3. 使用using指令

使用using指令可以將命名空間中的所有名稱引入當前作用域,這樣你就可以直接使用這些名稱而不需要命名空間前綴。但這種方法可能會導致名稱衝突,特別是當引入多個命名空間中有相同名稱的成員時。例如:

using namespace MyNamespace;

int main() 
{
    myFunction(); // 直接調用,無需前綴
    int value = myVariable; // 直接訪問
    std::cout<<value<<std::endl;
    return 0;
}

4. 嵌套命名空間

考慮有如下嵌套命名空間Outer::Inner,並在內部定義了innerFunction:

namespace Outer 
{
    namespace Inner 
    {
        void innerFunction() 
        {
            // 函數實現
            std::cout<<"void innerFunction()"<<std::endl;
        }
    }
}

在C++17及之後,可以使用嵌套命名空間的簡化寫法:

namespace Outer::Inner 
{
    void innerFunction() 
    {
        // 實現
         std::cout<<"void innerFunction()"<<std::endl;
    }
}

使用完全限定名訪問:

int main() {
    Outer::Inner::innerFunction(); // 直接調用嵌套命名空間中的函數
    return 0;
}

輸出:

void innerFunction()

或者使用using指令或聲明簡化訪問:

using namespace Outer::Inner; // 引入嵌套命名空間
// 或者
using Outer::Inner::innerFunction;

int main() {
    innerFunction(); // 直接調用
    return 0;
}

輸出:

void innerFunction()

使用注意事項

  • 精確性:直接使用完全限定名是最精確的方式,可以避免任何潛在的命名衝突。
  • 簡潔性與清晰性using聲明和using指令可以使代碼更簡潔,但過度使用可能會降低代碼的清晰性和可維護性,特別是在大型項目或者使用多個庫時。
  • 作用域考慮:使用using聲明和using指令時,應該考慮到它們的作用域。通常,將它們放在函數內部或者局部作用域內可以減少潛在的命名衝突和其他問題。

命名空間的作用域

使用using namespace命名空間名稱引入,可以將命名空間中的所有成員引入到當前作用域中,可以直接使用命名空間中的成員,而不需要使用命名空間前綴。

#include <iostream>
using namespace std;
namespace A
{
    int a = 10;
    int b = 66;
    int c = 108;
}
namespace B
{
    int a = 10;
    int b = 6;
    int c = 109;
}
int a = 36;

using namespace A;
using namespace B;

int main()
{
    //std::cout<<a<<std::endl;//這種寫法是錯誤的,因為全局中定義了a,命名空間tmh中的a也展開在了全局域
    std::cout<<::a<<std::endl;//正確:訪問全局的a,::左邊空白表示全局域
    std::cout<<A::a<<std::endl;//正確:訪問A中的a
    //std::cout<<b<<std::endl;//錯誤,應嚴格寫出哪個命名空間的b
    int c = 999;
    c++;//當前局部的c設置成999,局部變量優先,沒有特別的指示優先使用局部域中的元素
    std::cout<<c<<std::endl;
    return 0;
}

輸出:

C++拓展及命名空間的使用_作用域_05


感謝你的收看,如果文章有錯誤,可以指出,我不勝感激,讓我們一起學習交流,如果文章可以給你一個小小幫助,可以給博主點一個小小的贊😘