1. 程式人生 > >c++冒號作用

c++冒號作用

重新 其中 math 存儲 ont 了吧 嵌套 運算 結構定義

轉自http://www.360doc.com/content/13/0605/11/3373961_290615318.shtml

1.冒號(:)用法

(1)表示機構內位域的定義(即該變量占幾個bit空間)

typedef struct _XXX{

unsigned char a:4;

unsigned char c;

} ; XXX

(2)構造函數後面的冒號起分割作用,是類給成員變量賦值的方法,初始化列表,更適用於成員變量的常量const型。

struct _XXX{

_XXX() : y(0xc0) {}

};

(3) public:和private:後面的冒號,表示後面定義的所有成員都是公有或私有的,直到下一個"public:”或"private:”出現為止。"private:"為默認處理。

(4)類名冒號後面的是用來定義類的繼承。

class 派生類名 : 繼承方式 基類名

{

派生類的成員

};

繼承方式:public、private和protected,默認處理是public。

2.雙冒號(::)用法

(1)表示“域操作符”

例:聲明了一個類A,類A裏聲明了一個成員函數void f(),但沒有在類的聲明裏給出f的定義,那麽在類外定義f時,

就要寫成void A::f(),表示這個f()函數是類A的成員函數。

(2)直接用在全局函數前,表示是全局函數

例:在VC裏,你可以在調用API 函數裏,在API函數名前加::

(3)表示引用成員函數及變量,作用域成員運算符

例:System::Math::Sqrt() 相當於System.Math.Sqrt()

一.單冒號(:)
有些信息在存儲時,並不需要占用一個完整的字節, 而只需占幾個或一個二進制位。例如在存放一個開關量時,只有0和1 兩種狀態, 用一位二進位即可。為了節省存儲空間,並使處理簡便,C語言又提供了一種數據結構,稱為“位域”或“位段”。所謂“位域”是把一個字節中的二進位劃分為幾個不同的區域,並說明每個區域的位數。每個域有一個域名,允許在程序中按域名進行操作。這樣就可以把幾個不同的對象用一個字節的二進制位域來表示。一、位域的定義和位域變量的說明位域定義與結構定義相仿,其形式為:

struct 位域結構名
{ 位域列表 };
其中位域列表的形式為: 類型說明符 位域名:位域長度
例如:
struct bs
{
int a:8;
int b:2;
int c:6;
};
位域變量的說明與結構變量說明的方式相同。 可采用先定義後說明,同時定義說明或者直接說明這三種方式。例如:
struct bs
{
int a:8;
int b:2;
int c:6;
}data;
說明data為bs變量,共占兩個字節。其中位域a占8位,位域b占2位,位域c占6位。對於位域的定義尚有以下幾點說明:
1. 一個位域必須存儲在同一個字節中,不能跨兩個字節。如一個字節所剩空間不夠存放另一位域時,應從下一單元起存放該位域。也可以有意使某位域從下一單元開始。例如:
struct bs
{
unsigned a:4
unsigned :0 /*空域*/
unsigned b:4 /*從下一單元開始存放*/
unsigned c:4
}


在這個位域定義中,a占第一字節的4位,後4位填0表示不使用,b從第二字節開始,占用4位,c占用4位。
2. 位域可以無位域名,這時它只用來作填充或調整位置。無名的位域是不能使用的。例如:
struct k
{
int a:1
int :2 /*該2位不能使用*/
int b:3
int c:2

};

從以上分析可以看出,位域在本質上就是一種結構類型, 不過其成員是按二進位分配的。

3、條件語句(? :)
與?構成條件語句,作用相當於if else,如下;
int a,b,c;
a=3;
b=2;
c=a>b?a:b;// 如果a>b成立,則反a賦給c,否則把b賦給c
條件語句的結構為:
條件表達式?表達式1:表達式2
當條件表達式為true時,表達式的值為表達式1的值,否則為表達式2的值。
幾點說明:
1)?:可以嵌套,但不推薦使用(難懂),下面的表達式你能看懂啥意思不?
int max = i>j ? i>k ? i : k : j>k ? j : k;
腦袋大了吧,呵呵。
2)?:具有很低的優先級,這個要註意哦,下面的程序執行結果是啥呢?
int i = 3;
int j = 2;
cout << i>j?i:j;// 出錯,<<比>具有更高的優先級,執行順序為 ((cout<<i)>j)?i:j,相當於是比較cout<<i與j的大小,然後根據比較結果決定表達式值為i或j,這顯然要出錯的,cout<<i的值是cout,不能跟整型數j進行比較。
cout << (i>j)?i:j;//輸出1或0,相當於(cout<<(i>j))作為判決條件,來決定表達式的值為i或j,而cout<<(i>j),i>j則輸出1否則0,然後再將(cout<<(i>j))作為?:的條件,如果cout正確執行則為1(true),否則為0(false),以此決定表達式值為i或j
cout <<(i>j?i:j);//i>j則輸出i,否則輸出j,表達式值為true如果cout正確執行,否則為false
更多的關於優先級的問題就不說了。

4、語句標簽
通常跟goto配合使用,如:
step1: a = f1();
....
goto step1;
這種作法也不是很推薦,原因在於它破壞了語句的順序執行,這樣的代價大家應該清楚吧。不過存在即為合理嘛,既然它還存在,肯定還是有它的用處有它的好處的,比如說,多層嵌套的退出(會比break continue直觀一點吧),也可以避免重復代碼之類之類的

5、switch語句中case後。
這個不說了,要是不會的話,我也沒話可說了。

6、匯編指令模板
具體參考:http://developer.e800.com.cn/articles/2006/43/1144846933898_1.html
7、類構造函數(Constructor)的初始化列表
在構造函數後面緊跟著冒號加初始化列表,各初始化變量之間以逗號(,)隔開。下面舉個例子。
class myClass
{
public :
myClass();// 構造函數,無返回類型,可以有參數列表,這裏省去
~myClass();// 析構函數
int a;
const int b;
}

myClass::myClass():a(1),b(1)// 初始化列表
{
}
上面的例子展示了冒號的這個用法,下面對這個用法進行幾點說明:
1)初始化列表的作用相當於在構造函數內進行相應成員變量的賦值,但兩者是有差別的。
在初始化列表中是對變量進行初始化,而在構造函數內是進行賦值操作。兩都的差別在對於像const類型數據的操作上表現得尤為明顯。我們知道,const類型的變量必須在定義時進行初始化,而不能對const型的變量進行賦值,因此const類型的成員變量只能(而且必須)在初始化列表中進行初始化,即下面的代碼將會出錯:
myClass::myClass()
{
a = 1;// 沒錯,效果相當於在初始化列表中進行初始化
b = 1;// 出錯,const變量不能進行賦值操作;
}
2)初始化的順序與成員變量聲名的順序相同。
先看一下下面的程序:
myClass::myClass():b(1),a(b)
{
}
這樣的執行結果a,b各是多少呢?b=1,a=1?不是,b=1而a是個隨機數。這一點是相當重要的哦,一般在初始化列表中進行初始化時,初始化的順序應與聲明的順序保持一致,防止出現不必要的錯誤。
3)對於繼承的類來說,在初始化列表中也可以進行基類的初始化,初始化的順序是先基類初始化,然後再根據該類自己的變量的聲明順序進行初始化。
8、聲明基類。
假設我們重新定義一個類,繼承自myClass類。定義方式如下:
class derivedClass : public myClass
{
// 略去
}
這裏的冒號起到的就是聲名基類的作用,在基類類名前面可以加public\private\protected等標簽,用於標識繼承的類型,也可以省略,省略的話,用class定義的類默認為private,用struct定義的類默認為public,至於具體各個標簽有什麽區別這裏就不說了。
與初始化列表一樣的,這裏也可以聲名多個基類,各基類之間用逗號(,)隔開。
二.雙冒號(::)用法
1.表示“域操作符”
例:聲明了一個類A,類A裏聲明了一個成員函數void f(),但沒有在類的聲明裏給出f的定義,那麽在類外定義f時,
就要寫成void A::f(),表示這個f()函數是類A的成員函數。
2.直接用在全局函數前,表示是全局函數
例:在VC裏,你可以在調用API 函數裏,在API函數名前加::
3.表示引用成員函數及變量,作用域成員運算符
例:System::Math::Sqrt() 相當於System.Math.Sqrt()
4.命名空間作用域符,即2直接用在全局函數前,表示是全局函數
在運算符等級中屬於最高級的!
using namespace 命名空間名(如,abc);
表示在以下程序代碼中所使用的標示符(如果此標示符在abc中定義)是abc中的,包括類型名(類),變量名,函數名,對象名。。。
using abc::標示符(i);
只表示在以下代碼中使用的標示符i是abc中的。
如果你要使用abc中的多個標示符的話,你就只能用
using abc::a;
using abc::b;
using abc::c;
...
等一個一個列舉出來!
當然用using 語句是比較方便的
但是不安全
(1)using namespace;萬一不同的兩個命名空間中使用了同名的標示符,系統則不能判斷,這個標示符是屬於哪個命名空間的;
(2)using abc::;萬一你的程序中也用到了一個函數(函數名與abc中的這個函數同名),那麽系統也不能判斷你使用的是abc中的那個函數,還是本程序中的那個函數;
最安全的辦法(當然也是最繁瑣的)
就是,每當你用到一個變量(函數...)時,你都要明確他的來歷(即屬於哪個命名空間)除非它沒有命名空間
例如:
#include <iostream>


int main ()
{
std::cout << "hello, world!" << std::endl;
}
這裏就用到了iostream文件中的兩個對象(cout,endl)
因為C++標準庫中絕大部分的函數,對象...都放在了命名空間std中
所以
上面的代碼就等同於
#include <iostream>
using std::cout;
using std::endl;
int main ()
{
cout << "hello, world!" << endl;
}


#include <iostream>
using namespace std;


int main ()
{
cout << "hello, world!" << endl;
}
重新舉個例子,再加以說明:
#include <iostream>
#include <string>


int main ()
{
int a;
std::string b;


std::cin >> a;
std::cin >> b;


std::cout << "hello, world!" << std::endl;


return 0;
}




1)using std::;


#include <iostream>
#include <string>
using std::cin;
using std::endl;
using std::string;


int main ()
{
int a;
string b;


cin >> a;
cin >> b;


std::cout << "hello, world!" << endl; //註意cout沒用用using


return 0;
}




2)using namespace ;
#include <iostream>
#include <string>
using namespace std;


int main ()
{
int a;
string b;


cin >> a;
cin >> b;


cout << "hello, world!" << endl;


return 0;
}
其中cout endl cin string都是std中的!



另:

C++作用域運算符::主要有2種應用方式。

其一,聲明一個類A,類A裏聲明了一個成員函數void f(),但沒有在類的聲明裏給出f的定義,那麽在類外定義f時,就要寫成void A::f(),表示這個f()函數是類A的成員函數。

其二,作用域可以
簡單分為:全局作用域,局部作用域,語句作用域
作用域優先級:範圍越小優先級越高
作用域運算符:"::"
如果希望在局部變量的作用域內使用同名的全局變量,可以在該變量前加上"::","::"稱為作用域運算符.

eg:

技術分享圖片
//作用域
#include <iostream>
using namespace std;

int avar=10; //全局變量avar

int main()
{
int avar=20; //局部變量avar

cout<<"avar is: "<<avar<<endl; //訪問局部變量
avar=25; //1 //修改局部變量
cout<<"avar is: "<<avar<<endl;

cout<<"avar is: "<<::avar<<endl; //訪問全局變量
::avar=30; //2 //修改全局變量
cout<<"avar is: "<<::avar<<endl;

return 0;
}
技術分享圖片

輸出結果依次為:20,25,10,30

c++冒號作用