枚舉:是被命名的整型常數的集合,通過對整型類型的重命名,可以更加直觀的表達。
結構體的理解
使用結構體(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 & operate = (const A & 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;
}