c++基础知识

来源:互联网 发布:wap页面纯文字游戏源码 编辑:程序博客网 时间:2024/06/13 10:42


  1. 命名空间
在c++中,名称可以是变量、函数、结构、枚举、类以及类和结构的成员。当随着项目的增大,名称相互冲突的可能性也将增大。使用多个厂商的类库时,可能导致名称冲突。例如,两个库可能都定义了名为List,Tree,和Node的类,但定义的方式不兼容,用户可能希望使用一个库的List类,而使用另一个库的Tree类。这种冲突被称为名称空间问题。下面介绍几个c++已有的名称空间属性和一些术语,一边理解概念。
声明区域(declaration region)。声明区域是可以在其中进行声明的区域。例如,可以在函数外面声明全局变量,对于这种变量,其声明区域为其声明所在的文件。对于函数中声明的变量,其声明区域为其声明所在的代码块。
潜在作用域(potential scope)。变量的潜在作用域从声明点开始,到其声明区域的结尾。因此潜在作用域比声明区域小,这是因为变量必须定义后才能使用。
然而,变量并非在其潜在作用域内的任何位置都是可见的。例如,它可能被另一个嵌套声明区域中声明的同名变量隐藏。例如,在函数中声明的局部变量(对于这种变量,声明区域为整个函数)将隐藏在同一个文件中声明的全局变量(对于这种变量,声明区域为整个文件)。变量对程序而言可见的范围被称为作用域(scope)。
c++关于全局变量和局部变量的规则定义了一种名称空间层次。每个声明区域都可以声明名称,这些名称独立于在其他声明区域中声明的名称。在一个函数声明的局部变量不会与在另一个函数中声明的局部变量发生冲突。
新的名称空间特性:通过定义一种新的来创建新命名的名称空间,这样做的目的之一是提供一个声明名称的区域。一个名称空间中的名称不会与另外一个名称空间相同名称发生冲突,同时允许程序的其他部分使用该名称空间的中生命的东西。例如,下面的代码:
namespace Jack{
double pail;
void fetch();
int pal;
struct Well{......};
}
namespace Jill{
double bucket (double n){......}
double fetch;
int pal;
struct Hill;
}
名称空间可以是全局的,也可以位于另一个名称空间中,但不能位于代码块中。因此在默认情况下,在名称空间中声明的名称的链接属性为外部的(除非它引用了常量)。
除了用户定义的名称空间外,还存在另一个名称空间——全局名称空间(global namespace)。它对应于文件级声明区域,因此前面所说的全局变量现在被描述为位于全局名称中。
任何名称空间中的名称都不会与其他名称空间中的名称发生冲突。因此,Jack中的fetch可以与Jill中的fetch共存。名称空间中的声明和定义规则同全局声明和定义规则相同。
  1. c++中的输入输出流(简称I/O)
c++程序把输入和输出看成字节流。输入时,程序从输入流中抽取字节;输出时,程序将字节插入到输出流中。
  1. 使用cin及其方法进行输入
cin对象将标准输入表示为字节点,通常情况下用键盘来生成这种字节流,常用的cin输入方法为:cin>>abc,而istream类对抽取运算符进行了重载,是之可以识别这些基本类型,unsigned/signed char&,short&,int&,unsigned int&,long&,unsigned long&,long long&,unsigned long long&,float&,double&,long double&,对于这些基本类型直接就用cin加抽取运算符>>就可以实现。有个问题就在于>>抽取运算符会跳过换行符且会忽略类似于空白,制表之类的字符,所以这样的一段程序是有问题的,而对于要输入一个字符串cin>>input,这样的方法来输入一个字符串,则遇到的空白换行,制表之类的,输入都会停止。
(2)使用cout进行输出
cout和<<运算符,<<可以识别的基本类型有,unsigned char,signed char,char,short,unsigned short,int,unsigned int,long,unsigned long,long long,unsigned long long,float,double, long double.
如果使用下面这条语句,而value是前面列出的类型之一,则c++程序将其对应于有相应的特征标的运算符函数:cout<<value;
3.重载(c++为什么支持重载)
所谓的函数重载就是指:在同一作用域内,一组函数的函数名相同,参数列表不同(个数不同,类型不同),返回值可同可不同。
那为什么c++支持重载呢?
从代码的编译到运行,在VC6.0或VS这种编译器下,它是系统直接完成翻译与链接,直接生成了运行结果。
编译器完成了部分翻译部分:
  1. 预处理
i:头文件的展开
ii:宏的替换
iii:去掉注释
iv:条件编译
  1. 编译过程:将高级语言转为汇编语言
  2. 汇编过程:汇编语言转换维二进制程序
链接部分:所引用的数据链接进来
比如一个函数的声明如下
void func(int x,int y)
在c语言中,编译器在编译后在库中的名字为_func
在c++中,编译器在编译后在库中的名字为_func_int_int还有一个函数声明如下:
void func(float x,float y);
同上在c语言和c++编译完成后他们在库中的名字分别为_func和func_float_float
在链接时,都是找名字进行链接的,就比如上面两个函数,在c语言中两个名字一样,就会在链接中报错。
c++中它们的名字不一样,所以就不会报错。
  1. c++缺省函数
所谓缺省函数,就是指在声明函数的某个参数的时候为之指定一个默认的值,在调用该函数的时候如果采用该默认值,你就无须指定该参数。缺省函数的主要使用原则:调动时你只能从最后一个参数开始进行缺省,假如你要省略一个参数,你必须省略它后面的所有参数,即带缺省值的参数必须放在参数表的最后面。缺省值必须是常量。显然这限制了缺省函数的数据类型,例如动态数组和界面类型的缺省参数只能是nil;至于记录类型,则根本不能用作缺省参数。缺省参数必须通过值参或常参传递。
  1. 指针和引用
指针是一块内存的地址值,而引用是一块内存的别名。
从概念上讲,指针的本质就是一个存放变量地址的变量,在逻辑上是独立的,可以被改变,包括其指向的地址和指向地址所存放的数据。
而引用时一个别名它在逻辑上不是独立的,它的存在具有依附性,所以引用在一开始就被初始化,而且其引用的对象在其整个生命周期中是不会被改变的(从头到尾都只依附于一个变量)。
在c++中,指针和引用经常用于函数的参数传递,然而,指针传递参数和引用传递参数是有很大的区别的。
指针传递参数本质是值传递的方式,传递的是一个地址值。值传递过程中,被调函数的形式参数作为被调函数的局部变量处理,也就是说,被调函数的形式参数的任何操作都是局部进行,不会影响主调函数的实参的值。
在引用传递的过程中,被调函数的形式参数虽然也作为局部变量在栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形式参数的任何操作都被处理成间接寻址,通过栈中存放的地址访问主调函数的实参变量,因此,被调函数对形式参数的操作会影响主调函数的实参变量。

指针和引用的区别
相同点:指针指向的是一块内存,它的内容是所指向内存的地址;引用是某块内存的别名。但是他们都是地址的概念。
不同点:
引用只能在定义的时候初始化一次,之后不可变;而指针可变。
引用没有const,而有指针const,const的指针不可变。
引用不能为空,而指针可以为空。
sizeof引用得到的是所指向变量(对象)的大小,而sizeof指针得到的是指针本身的大小。
指针和引用的自增运算意义不一样。
引用是类型安全的,而指针不是(引用比指针多了类型检查)
最后我们来说一下引用做参数,返回值的方法。
  1. 引用做函数参数
接下来举一个简单的例子
#include <iostream>
using namespace std;
void f(int &b)
{
     b++;
}
int main()
{
     int a = 3;
f(a);
cout<<a<<endl;
return 0;
}


这里我们可以看到输出的a是4,也就是说调用函数f将a传递给函数f的形参后返回的值增加了1,即形参的增加影响了实参,也就应征了形参b是a的别名。
  1. 引用做返回值
同样的我们也来用一个例子来说明。

#include <iostream>
using namespace std;
int& f(int *p)
{
(*p)++;
return *p;
}
int main()
{
int a = 3;
int b;
b = f(&a)*5;
f(&a)+=10;
cout<<”b=”<<b<<”  ”<<”a=”<<a<<endl;
return 0;
}

从这个例子中我们知道了返回的值b=20,a=15。可以看出函数返回一个(*p)的引用,即a的引用,此引用可做a的左值进行运算。


原创粉丝点击