小白學習大型C++源碼項目系列之枚舉類(enum class或是enum struct)

枚舉:是被命名的整型常數的集合,通過對整型類型的重命名,可以更加直觀的表達。

結構體的理解

使用結構體(Struct)來存儲相同類型或不同類型數據的集合。
結構體也是一種數據類型,它由程序員自己定義,可以包含多個其他類型的數據。
像 int、float、char 等是由C語言本身提供的數據類型,不能再進行分拆,我們稱之爲基本數據類型;而結構體可以包含多個基本類型的數據,也可以包含其他的結構體,我們將它稱爲複雜數據類型或構造數據類型。

結構體的兩種常見分類

標準結構體:標準情況“struct 結構體名 { 數據類型…… }結構體變量名;”
匿名結構體:鎖定變量變量個數“struct { 數據類型…… }結構體變量名;”即沒有結構體名

先定義結構體類型,在定義變量

struct stu 
{ //定義一個結構體,這種數據類型是 “struct stu”;
	char *name; //姓名
	int num; //學號
	int age; //年齡
	char group; //所在學習小組
	float score; //成績
};

struct stu stu1, stu2; //stu1、stu2就是結構體變量;

定義了兩個變量 stu1 和 stu2,它們都是 stu 類型,都由 5 個成員組成。
注意關鍵字struct不能少。stu 就像一個“模板”,定義出來的變量都具有相同的性質。

結構體變量的引用方式

1) 結構體變量名.成員名:stu1.name
2) 結構體指針變量->成員名:ps -> name

3) (*結構體指針變量).成員名:(*ps).name 因爲優先級的問題,所以要加括號
4) 結構體變量數組名.成員名:stu[0].name

我項目中的用法

struct Config
{
    bool is_table_test_ = false;
};
// 定義一個結構體變量
Config config_;

結構體作爲函數的返回值

原來結構體可以作爲函數的參數,也可以作爲函數的返回值。
這麼用屬於函數的傳值調用,函數中使用的是結構體的副本,函數中的操作不會改變原結構體的值,但是會犧牲一些速度。
用指針傳遞結構體變量的話,屬於傳址調用,是直接操作結構體,所以函數中的操作直接反應到結構體上。
OpenCV中這麼做,一是結構體比較小,影響內存開銷比較小;二是防止改變結構體本身吧。一點淺見。

#include<stdio.h>
//定義一個結構體
typedef struct Point
{
       int x;
       int y;
}Point;

//使用一個結構體變量作爲函數的參數
void Display(Point point)
{
       printf("x is %d\n",point.x);
       printf("y is %d\n",point.y);
       /*********若使用C++,則如下*************
       std::cout<<"x is "<<point.x<<std::endl;
       std::cout<<"y is "<<point.y<<std::endl;
       **************************************/
}

//使用結構體變量作爲函數的返回值
Point SetPoint(int x,int y)
{
       Point point;
       point.x=x;
       point.y=y;
       return point;
}

//主函數
int main(int atgc,char * argv[])
{
       Point point;
       point=SetPoint(2,3);
       Display(point);
       return 0;
}

運行結果

x is 2
y is 3

const 用於修飾“返回引用”函數的返回值

如果函數返回值採用“值傳遞方式”,由於函數會把返回值複製到外部臨時的存儲單元中,加const 修飾沒有任何價值。
例如把函數int GetInt(void) 寫成const int GetInt(void)是沒有意義的。

如果返回值不是內部數據類型,將函數MyClass GetObj(void) 改寫爲const Myclass & GetObj(void)的確能提高效率。
但此時千萬千萬要小心,一定要搞清楚函數究竟是想返回一個對象的“拷貝”還是僅返回“別名”就可以了,否則程序會出錯。

這裏對函數返回值使用 const 的目的在於限制不能將函數調用表達式作爲左值使用。例如有如下函數:

int & min ( int &i, int &j);

可以對函數調用進行賦值,因爲它返回的是左值: min ( a , b )=4;

但是,如果對函數的返回值限定爲 const 的,即丁奕:const int & min ( int & i, int &j );

那麼,就不能對 min ( a, b ) 調用進行賦值了。

事實上,函數返回值採用“引用傳遞”的場合並不多,這種方式一般只出現在類的賦值函數中,目的是爲了實現鏈式表達。

class A
{
A &amp; operate = (const A &amp; other); // 賦值函數
} ;
A a, b, c; // a, b, c 爲A 的對象
a = b = c; // 正常的鏈式賦值
(a = b) = c; // 不正常的鏈式賦值,但合法

如果將賦值函數的返回值加const 修飾,那麼該返回值的內容不允許被改動。
上例中,語句 a = b = c 仍然正確,但是語句 (a = b) = c 則是非法的。

枚舉類

有的時候一個類的對象是有限且固定的,這種情況下我們使用枚舉類就比較方便。

將enum封裝到類的內部,enum class 和 enum struct 是等價的。

枚舉體的聲明和定義使用 enum class或是enum struct, 二者是等價的。
使用enum class\enum struct不會與現存的enum關鍵詞衝突。
而且enum class\enum struct具有更好的類型安全和類似封裝的特性(scoped nature)。

enum class color{red,green,yellow}; 
enum class colorx{red,green=100,yellow}; 

用enum定義的枚舉體是一個不具有封裝性(不知道如何翻譯是好:unscoped enumeration)的枚舉體,他的成員可以在enum的大括號外被直接訪問。而用enum class或是enum struct(二者在語法上是等價的)定義的枚舉體是具有封裝性的(scoped enumeration),他的成員同過成員名直接訪問,而應通過域運算符來訪問。

   #include <iostream>
     
    enum class color{red,black};
    enum colorx{green,yellow};
     
    int main() {
        color::red;//用域運算符訪問color的成員
        green;//直接訪問colorx的成員
        colorx::green;//用域運算符訪問colorx的成員
        std::cin.get();
        return 0;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章