cc++中单冒号(:)和双冒号(::)的⽤法
转blog.csdn/chw1989/article/details/7480375
⼀.单冒号(:)
有些信息在存储时,并不需要占⽤⼀个完整的字节,⽽只需占⼏个或⼀个⼆进制位。例如在存放⼀个开关量时,只有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;
条件语句的结构为:
条件表达式?表达式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、汇编指令模板
具体参考:developer.e800/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变量不能进⾏赋值操作;
}
先看⼀下下⾯的程序:
myClass::myClass():b(1),a(b)
{
}
这样的执⾏结果a,b各是多少呢?b=1,a=1?不是,b=1⽽a是个随机数。这⼀点是相当重要的哦,⼀般在初始化列表中进⾏初始化时,初始化的顺序应与声明的顺序保持⼀致,防⽌出现不必要的错误。
c++string类型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 ()
{
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中的!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论