C中单冒号与双冒号的用法.docx
《C中单冒号与双冒号的用法.docx》由会员分享,可在线阅读,更多相关《C中单冒号与双冒号的用法.docx(8页珍藏版)》请在冰豆网上搜索。
C中单冒号与双冒号的用法
C++中单冒号与双冒号的用法
C++单冒号与双冒号的作用1.冒号(:
)用法
(1)表示机构内位域的定义(即该变量占几个bit空间)typedefstruct_XXX{unsignedchara:
4;unsignedcharc;};XXX
(2)构造函数后面的冒号起分割作用,是类给成员变量赋值的方法,初始化列表,更适用于成员变量的常量const型。
struct_XXX{_XXX():
y(0xc0){}};(3)public:
和private:
后面的冒号,表示后面定义的所有成员都是公有或私有的,直到下一个"public:
”或"private:
”出现为止。
"private:
"为默认处理。
(4)类名冒号后面的是用来定义类的继承。
class派生类名:
继承方式基类名{派生类的成员};继承方式:
public、private和protected,默认处理是public。
2.双冒号(:
:
)用法
(1)表示“域操作符”例:
声明了一个类A,类A里声明了一个成员函数voidf(),但没有在类的声明里给出f的定义,那么在类外定义f时,就要写成voidA:
:
f(),表示这个f()函数是类A的成员函数。
(2)直接用在全局函数前,表示是全局函数例:
在VC里,你可以在调用API函数里,在API函数名前加:
:
(3)表示引用成员函数及变量,作用域成员运算符例:
System:
:
Math:
:
Sqrt()相当于System.Math.Sqrt()一.单冒号(:
)
有些信息在存储时,并不需要占用一个完整的字节,而只需占几个或一个二进制位。
例如在存放一个开关量时,只有0和1两种状态,用一位二进位即可。
为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,称为“位域”或“位段”。
所谓“位域”是把一个字节中的二进位划分为几个不同的区域,并说明每个区域的位数。
每个域有一个域名,允许在程序中按域名进行操作。
这样就可以把几个不同的对象用一个字节的二进制位域来表示。
一、位域的定义和位域变量的说明位域定义与结构定义相仿,其形式为:
struct位域结构名
{位域列表};
其中位域列表的形式为:
类型说明符位域名:
位域长度
例如:
structbs
{
inta:
8;
intb:
2;
intc:
6;
};
位域变量的说明与结构变量说明的方式相同。
可采用先定义后说明,同时定义说明或者直接说明这三种方式。
例如:
structbs
{
inta:
8;
intb:
2;
intc:
6;
}data;
说明data为bs变量,共占两个字节。
其中位域a占8位,位域b占2位,位域c占6位。
对于位域的定义尚有以下几点说明:
1.一个位域必须存储在同一个字节中,不能跨两个字节。
如一个字节所剩空间不够存放另一位域时,应从下一单元起存放该位域。
也可以有意使某位域从下一单元开始。
例如:
structbs
{
unsigneda:
4
unsigned:
0/*空域*/
unsignedb:
4/*从下一单元开始存放*/
unsignedc:
4
}在这个位域定义中,a占第一字节的4位,后4位填0表示不使用,b从第二字节开始,占用4位,c占用4位。
2.位域可以无位域名,这时它只用来作填充或调整位置。
无名的位域是不能使用的。
例如:
structk
{
inta:
1
int:
2/*该2位不能使用*/
intb:
3
intc:
2
};从以上分析可以看出,位域在本质上就是一种结构类型,不过其成员是按二进位分配的。
3、条件语句(?
:
)
与?
构成条件语句,作用相当于ifelse,如下;
inta,b,c;
a=3;
b=2;
c=a>b?
a:
b;//如果a>b成立,则反a赋给c,否则把b赋给c
条件语句的结构为:
条件表达式?
表达式1:
表达式2
当条件表达式为true时,表达式的值为表达式1的值,否则为表达式2的值。
几点说明:
1)?
:
可以嵌套,但不推荐使用(难懂),下面的表达式你能看懂啥意思不?
intmax=i>j?
i>k?
i:
k:
j>k?
j:
k;
脑袋大了吧,呵呵。
2)?
:
具有很低的优先级,这个要注意哦,下面的程序执行结果是啥呢?
inti=3;
intj=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();
....
gotostep1;
这种作法也不是很推荐,原因在于它破坏了语句的顺序执行,这样的代价大家应该清楚吧。
不过存在即为合理嘛,既然它还存在,肯定还是有它的用处有它的好处的,比如说,多层嵌套的退出(会比breakcontinue直观一点吧),也可以避免重复代码之类之类的
5、switch语句中case后。
这个不说了,要是不会的话,我也没话可说了。
6、汇编指令模板
具体参考:
7、类构造函数(Constructor)的初始化列表
在构造函数后面紧跟着冒号加初始化列表,各初始化变量之间以逗号(,)隔开。
下面举个例子。
classmyClass
{
public:
myClass();//构造函数,无返回类型,可以有参数列表,这里省去
~myClass();//析构函数
inta;
constintb;
}
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类。
定义方式如下:
classderivedClass:
publicmyClass
{
//略去
}
这里的冒号起到的就是声名基类的作用,在基类类名前面可以加public\private\protected等标签,用于标识继承的类型,也可以省略,省略的话,用class定义的类默认为private,用struct定义的类默认为public,至于具体各个标签有什么区别这里就不说了。
与初始化列表一样的,这里也可以声名多个基类,各基类之间用逗号(,)隔开。
二.双冒号(:
:
)用法
1.表示“域操作符”
例:
声明了一个类A,类A里声明了一个成员函数voidf(),但没有在类的声明里给出f的定义,那么在类外定义f时,
就要写成voidA:
:
f(),表示这个f()函数是类A的成员函数。
2.直接用在全局函数前,表示是全局函数
例:
在VC里,你可以在调用API函数里,在API函数名前加:
:
3.表示引用成员函数及变量,作用域成员运算符
例:
System:
:
Math:
:
Sqrt()相当于System.Math.Sqrt()
4.命名空间作用域符,即2直接用在全局函数前,表示是全局函数
在运算符等级中属于最高级的!
usingnamespace命名空间名(如,abc);
表示在以下程序代码中所使用的标示符(如果此标示符在abc中定义)是abc中的,包括类型名(类),变量名,函数名,对象名。
。
。
usingabc:
:
标示符(i);
只表示在以下代码中使用的标示符i是abc中的。
如果你要使用abc中的多个标示符的话,你就只能用
usingabc:
:
a;
usingabc:
:
b;
usingabc:
:
c;
...
等一个一个列举出来!
当然用using语句是比较方便的
但是不安全
(1)usingnamespace;万一不同的两个命名空间中使用了同名的标示符,系统则不能判断,这个标示符是属于哪个命名空间的;
(2)usingabc:
:
;万一你的程序中也用到了一个函数(函数名与abc中的这个函数同名),那么系统也不能判断你使用的是abc中的那个函数,还是本程序中的那个函数;
最安全的办法(当然也是最繁琐的)
就是,每当你用到一个变量(函数...)时,你都要明确他的来历(即属于哪个命名空间)除非它没有命名空间
例如:
#include<iostream>intmain()
{
std:
:
cout<<"hello,world!
"<<std:
:
endl;
}
这里就用到了iostream文件中的两个对象(cout,endl)
因为C++标准库中绝大部分的函数,对象...都放在了命名空间std中
所以
上面的代码就等同于
#include<iostream>
usingstd:
:
cout;
usingstd:
:
endl;
intmain()
{
cout<<"hello,world!
"<<endl;
}#include<iostream>
usingnamespacestd;intmain()
{
cout<<"hello,world!
"<<endl;
}
重新举个例子,再加以说明:
#include<iostream>
#include<string>intmain()
{
inta;
std:
:
stringb;std:
:
cin>>a;
std:
:
cin>>b;std:
:
cout<<"hello,world!
"<<std:
:
endl;return0;
}1)usingstd:
:
;#include<iostream>
#include<string>
usingstd:
:
cin;
usingstd:
:
endl;
usingstd:
:
string;intmain()
{
inta;
stringb;cin>>a;
cin>>b;std:
:
cout<<"hello,world!
"<<endl;//注意cout没用用usingreturn0;
}2)usingnamespace;
#include<iostream>
#include<string>
usingnamespacestd;intmain()
{
inta;
stringb;cin>>a;
cin>>b;cout<<"hello,world!
"<<endl;return0;
}
其中coutendlcinstring都是std中的!