文章目錄
- 一、C++ 修飾符類型
- 1. 訪問修飾符(Access Modifiers)
- 2. 存儲類修飾符(Storage Class Specifiers)
- 3. 類型修飾符(Type Modifiers)
- 4. 函數修飾符
- 二、C++ 修飾符類型-案例
- 1. 訪問修飾符案例
- 2. 存儲類修飾符案例
- 3. 類型修飾符案例
- 4. 函數修飾符案例
- 三、C++ 中的類型限定符
- 1. `const` 限定符
- 2. `volatile` 限定符
- 四、相關鏈接

一、C++ 修飾符類型
在C++中,修飾符(Modifiers)用于改變變量、函數、類成員等的默認行為或屬性。這些修飾符可以分為幾個主要的類別,包括訪問修飾符(Access Modifiers)、存儲類修飾符(Storage Class Specifiers)、類型修飾符(Type Modifiers)以及函數修飾符(如const
和noexcept
用于函數)。下面是對這些修飾符類型的一些簡要說明:
1. 訪問修飾符(Access Modifiers)
訪問修飾符控制類成員的訪問權限。
public
:類外部可以訪問。protected
:只能被其派生類以及該類的成員訪問。private
:只能被該類內部的成員函數、友元函數以及類本身訪問。
2. 存儲類修飾符(Storage Class Specifiers)
存儲類修飾符決定了變量/函數的存儲方式和作用域。
auto
:自動變量(局部變量),但現代C++中auto
關鍵字有了新的用途,即自動類型推導。register
:建議編譯器盡可能將變量存儲在寄存器中(但現在很多編譯器都忽略了這個建議)。static
:- 對于局部變量,
static
延長了變量的生命周期,但變量的作用域不變。 - 對于全局變量和函數,
static
限制了它們的鏈接性(linkage),使得它們只在定義它們的文件內可見。 - 對于類成員變量,
static
使得變量成為所有對象的共享變量。
- 對于局部變量,
extern
:聲明變量或函數是在別的文件中定義的,或者是全局的。thread_local
(C++11):聲明變量的生命周期與線程相同,每個線程都擁有該變量的一個獨立實例。
3. 類型修飾符(Type Modifiers)
類型修飾符影響變量或函數的類型或特性。
const
:表示變量或函數的返回值不可修改。volatile
:告訴編譯器該變量的值可能會在程序的控制之外被改變(例如,被操作系統、硬件或其他線程改變)。signed
和unsigned
:用于整數類型,指定變量是有符號還是無符號的。long
和short
:用于整數類型,指定變量的存儲大小。enum
:定義枚舉類型。struct
和class
:定義復合數據類型。
4. 函數修飾符
const
:用于成員函數,表示該函數不會修改對象的任何成員變量(如果是非靜態成員函數)。noexcept
(C++11):指定函數不會拋出任何異常。如果函數確實拋出了異常,程序會調用std::terminate()
立即終止。virtual
:允許在派生類中重寫基類的成員函數。override
(C++11):明確指定一個成員函數是重寫了基類中的虛函數。final
(C++11):用于類和方法,防止類被繼承或方法被進一步重寫。
二、C++ 修飾符類型-案例
當然,下面我將提供幾個使用不同C++修飾符的案例代碼。這些案例將涵蓋訪問修飾符、存儲類修飾符、類型修飾符以及函數修飾符。
1. 訪問修飾符案例
class MyClass {
public:void publicFunction() {// 公有成員函數,可以在類外部訪問}protected:void protectedFunction() {// 保護成員函數,只能在類內部、派生類以及友元中訪問}private:void privateFunction() {// 私有成員函數,只能在類內部訪問}
};
2. 存儲類修飾符案例
#include <iostream>class MyClass {
public:static int staticVar; // 靜態成員變量,所有對象共享void printStaticVar() {std::cout << staticVar << std::endl;}
};int MyClass::staticVar = 0; // 靜態成員變量的定義int main() {MyClass obj1, obj2;obj1.staticVar = 10; // 通過任一對象修改obj2.printStaticVar(); // 輸出 10extern int globalVar; // 聲明外部變量// 假設 globalVar 在其他地方定義并初始化// register 修飾符在現代C++中通常不推薦使用,因為它對編譯器來說是建議性的// register int regVar; // 示例,但通常不推薦這樣做return 0;
}// 假設在另一個文件中定義的 globalVar
// int globalVar = 20;
3. 類型修飾符案例
#include <iostream>class MyClass {
public:void display() const { // const 成員函數,保證不修改任何成員變量std::cout << "Display function called" << std::endl;}// 使用 signed 和 unsignedvoid showIntegers() {signed int sInt = -10;unsigned int uInt = 10;std::cout << "Signed: " << sInt << ", Unsigned: " << uInt << std::endl;}
};int main() {MyClass obj;obj.display();obj.showIntegers();return 0;
}
4. 函數修飾符案例
#include <iostream>
#include <stdexcept>class MyClass {
public:virtual void virtualFunction() {// 虛函數,可以在派生類中被重寫std::cout << "Base class function" << std::endl;}void myFunction() noexcept {// noexcept 函數,保證不拋出異常// 如果嘗試拋出異常,程序將調用 std::terminate()// 注意:這里的函數體沒有實際拋出異常}void overriddenFunction() override { // 使用 override 明確指定重寫// 這里是重寫基類中的虛函數(假設基類中有相應的虛函數聲明)std::cout << "Overridden function" << std::endl;}// 注意:final 修飾符用于類和方法時,表示該類不能被繼承或該方法不能在派生類中被重寫// 這里沒有直接展示 final 的用法,因為它需要在類的繼承關系中體現
};// 假設有 MyClass 的派生類,可以展示 virtual 和 override 的用法
// class DerivedClass : public MyClass {
// public:
// void virtualFunction() override {
// // 重寫 MyClass 中的 virtualFunction
// std::cout << "Derived class function" << std::endl;
// }
// };int main() {MyClass obj;obj.virtualFunction(); // 調用基類函數obj.myFunction(); // 調用 noexcept 函數// obj.overriddenFunction(); // 如果 MyClass 中有對應的虛函數聲明,則可以這樣調用// 演示 noexcept 的異常處理(盡管這個例子沒有實際拋出異常)// try {// throw std::runtime_error("Error");// obj.myFunction(); // 假設 myFunction 內部有拋出異常的代碼,但由于 noexcept,這里不會執行// } catch (...) {// std::cout << "Exception caught, but myFunction() is noexcept and should not have thrown" << std::endl;// // 注意:如果 myFunction 實際上是 noexcept 的,并且拋出了異常,程序將不會進入這個 catch 塊// // 相反,它將調用 std::terminate()// }
}
三、C++ 中的類型限定符
在C++中,類型限定符(Type Qualifiers)主要用于限制或改變變量的類型或行為。最常見的類型限定符包括const
和volatile
。這些限定符可以與基本數據類型、指針、引用等一起使用,以提供額外的信息給編譯器和開發者。
1. const
限定符
const
限定符用于聲明一個變量為常量,意味著一旦該變量被初始化后,其值就不能被改變。const
也可以用于修飾函數參數、返回值以及成員函數,以表明這些函數不會(或不應該)修改任何數據。
案例代碼:
#include <iostream>void display(const int& value) {// 嘗試修改value會導致編譯錯誤// value = 10; // 編譯錯誤std::cout << "Value: " << value << std::endl;
}int main() {const int a = 5; // a是一個常量,其值不能被修改// a = 10; // 編譯錯誤display(a); // 傳遞a的引用,但由于是const,所以display函數內部不能修改它const int* ptr = &a; // ptr是一個指向常量的指針,不能通過ptr修改a的值// *ptr = 10; // 編譯錯誤// 但是,ptr本身是可以被修改的,指向另一個常量const int b = 20;ptr = &b; // 合法,ptr現在指向b// 指向常量的指針的常量(即,指針本身也是常量)int c = 30;const int* const cPtr = &c; // cPtr不能指向其他地址,也不能通過cPtr修改c的值// cPtr = &a; // 編譯錯誤,cPtr是常量return 0;
}
2. volatile
限定符
volatile
限定符告訴編譯器該變量的值可能會以編譯器無法預見的方式被改變。這通常用于嵌入式編程、多線程編程或訪問由硬件直接修改的內存位置時。編譯器在優化代碼時會考慮變量的volatile
屬性,以確保每次訪問該變量時都直接從其內存地址讀取值,而不是使用可能已存儲在寄存器中的緩存值。
案例代碼:(這個案例可能不那么直觀,因為它依賴于外部條件來改變變量的值)
#include <iostream>// 假設有一個硬件寄存器,其值可能會被外部事件(如中斷)改變
volatile int hardwareRegister = 0; // 聲明為volatile,因為值可能隨時改變void checkHardwareStatus() {// 循環檢查hardwareRegister的值,直到它變為非零(表示某種硬件事件)while (hardwareRegister == 0) {// 在這里,編譯器不會優化掉對hardwareRegister的訪問// 即使它看起來像是在一個無限循環中}// 處理硬件事件...std::cout << "Hardware event detected!" << std::endl;
}int main() {// 在實際應用中,hardwareRegister的值可能由中斷服務例程(ISR)改變// 這里我們模擬這個行為// ...(模擬代碼省略)checkHardwareStatus();return 0;
}
volatile
的使用應謹慎,因為它會阻止編譯器進行某些優化,這可能會降低程序的性能。只有當確實需要時才應使用volatile
。
四、相關鏈接
- Visual Studio Code下載地址
- Sublime Text下載地址
- 「C++系列」C++簡介、應用領域
- 「C++系列」C++ 基本語法
- 「C++系列」C++ 數據類型
- 「C++系列」C++ 變量類型
- 「C++系列」C++ 變量作用域
- 「C++系列」C++ 常量知識點-細致講解