知识点:
1.命名空间
2.C++基本的输入输出流(简单介绍一下就行)
3.重载(C++为什么支持重载?)
4.C++缺省参数
5.指针和引用(概念、使用方法、做参数、做返回值的作用,指针和引用的区别)
1.命名空间 : namespace
namespace,即“命名空间”,也称“名字空间”。VS.NET中的各种语言使用的一种代码组织的形式通过名称空间来分类,区别不同的代码功能。同时也是VS.NET中所有类的完全名称的一部分。
首先,来看它是如何使用的(::是作用域运算分解符):
(1) 引用 using namespace std;
#include <iostream>
using namespace std;
namespace A1
{
int a = 10;
}
namespace A2
{
int a = 20;
}
int a = 30;
int main()
{
cout<<A1::a<<endl; //使用A1空间 a=10
cout<<A2::a<<endl; //使用A2空间 a=20
cout<<::a<<endl; //使用全局域空间
cout<<a<<endl;
return 0;
}
(2) 输出时还可以 采用 std::count<<......<<std::endl的方式;
此外,
命名空间可以是全局的,也可以位于另一个命名空间之中,但是不能位于类和代码块中。所以,在命名空间中声明的名称(标识符),默认具有外部链接特性(除非它引用了常量)。
在所有命名空间之外,还存在一个全局命名空间,它对应于文件级的声明域。因此,在命名空间机制中,原来的全局变量,现在被认为位于全局命名空间中。
标准C++库(不包括标准C库)中所包含的所有内容(包括常量、变量、结构、类和函数等)都被定义在命名空间std(standard标准)中了。
2.C++的基本输入输出流
(1)标准输入流(cin):
cin是iostream类的对象,它从标准输入设备(键盘)获取数据,程序中的变量通过流提取符“>>”从流中提取数据。流提取符“>>”从流中提取数据时通常跳过输入流中的空格、tab键、换行符等空白字符。
(2)标准输出流(cout):
cont是console output的缩写,意为在控制台(终端显示器)的输出。
①cout不是C++预定义的关键字,它是ostream流类的对象,在iostream中定义。 顾名思义,流是流动的数据,cout流是流向显示器的数据。cout流中的数据是用流插入运算符“<<”顺序加入的。如果有:
cout<<"I "<<"study C++ "<<"very hard.";
按顺序将字符串"I ", "study C++ ", "very hard."插人到cout流中,cout就将它们送到显示器,在显示器上输出字符串"I study C++ very hard."。cout流是容纳数据的载体,它并不是一个运算符。人们关心的是cout流中的内容,也就是向显示器输出什么。
②cout流在内存中对应开辟了一个缓冲区,用来存放流中的数据,当向cout流插 人一个endl时,不论缓冲区是否已满,都立即输出流中所有数据,然后插入一个换行符, 并刷新流(清空缓冲区)。注意如果插人一个换行符”\n“(如cout<<a<<"\n"),则只输出和换行,而不刷新cout流(但并不是所有编译系统都体现出这一区别)。
(3)标准错误流(cerr,clog):
①cerr流对象是标准错误流,cerr流已被指定为与显示器关联。
②7clog流对象也是标准错误流,它是console log的缩写。它的作用和cerr相同,都是在终端显示器上显示出错信息。区别:cerr是不经过缓冲区,直接向显示器上输出有关信息,而clog中的信息存放在缓冲区中,缓冲区满后或遇endl时向显示器输出。
下面演示一个标准输入输出流的简单程序:
int main()
{
int a = 0;
cout<<"请输入一个整数"<<endl;
cin>>a;
cout<<oct<<a<<endl; //8进制输出
cout<<dec<<a<<endl; //10进制输出,不写类型默认输出十进制
cout<<hex<<a<<endl; //16进制输出
cout<<"请输入一个布尔值0或者1"<<endl;
bool b = 1; //定义布尔类型
cin>>b;
cout<<boolalpha<<b<<endl; //以布尔类型输出
return 0;
}
3.重载(C++为什么支持重载)
重载:在同一个作用域中,函数名相同,参数不同(类型不同,个数不同)。
func(int a, int b); | func(int a); | func(double a, double b); //函数重载
①首先,我们需要了解的是,在c中,要求在同一个作用域中,函数名唯一。就是不允许函数同名。
而在C++中,要求同一个作用域中函数签名唯一。函数签名是函数名+参数列表。就是说允许函数名相同但参数列表不同的函数存在。可见,函数重载跟返回类型没什么关系。
②那么为什么C++允许函数签名唯一呢?
代码段在被编译器编译的时候,会根据函数名生成函数的调用地址。
C编译器编译之后,函数名不变。
而C++编译器编译之后,函数名就会发生命名置换。比如说代码中的函数是
int function(int a,int b,double c)
{
cout<<a<<b<<c<<endl;
}
gcc 编译,命名置换后,会变成_Z8functioniid。
其中_Z是 gcc 编译器的保留字,不同的编译器,生成的保留字也会不一样,8是函数名的字符数量,iid则是参数列表的缩写。
经过这样一个操作时候,即使是函数名相同,但只要参数列表不同,那么编译之后生成的函数名实际上是不同的。
int sum(int x=0, int y=100, int z=0) { return x+y+z; }
int sum(int x, int y=100, int z=0) { ... } //这是正确的
int sum(int x, int y, int z=0) { ... } //这是正确的
int plus(int x, int y=100, int z) { ... } //这是错误的
指针传递参数本质上是值传递的方式,它所传递的是一个地址值。值传递过程中,被调函数的形式参数作为被调函数的局部变量处理,即在栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值。(这里是在说实参指针本身的地址值不会变)
引用传递过程中,被调函数的形式参数虽然也作为局部变量在栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址(int &a的形式)。被调函数对形参的任何操作都被处理成间接寻址,即通过栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量。
下面再具体谈一下 引用:
(1)引用被创建的同时必须被初始化(指针则可以在任何时候被初始化)。
(2)不能有NULL引用,引用必须与合法的存储单元关联(指针则可以是NULL)。
(3)一旦引用被初始化,就不能改变引用的关系(指针则可以随时改变所指的对象)。
引用引入了对象的一个同义词。定义引用的表示方法与定义指针相似,只是用&代替了*。例如:
Point &pt2=pt1;
pt1.offset(2,2);
pt1和pt2都具有(12,12)的值。引用必须在定义时马上被初始化,因为它必须是某个东西的同义词。你不能先定义一个引用后才初始化它。例如下面语句是非法的:
Point &pt3;
pt3=pt1;
引用的两个主要用途:作为函数参数以及从函数中返回左值。
1、传递可变参数
传统的c中,函数在调用时参数是通过值来传递的,这就是说函数的参数不具备返回值的能力。所以在传统的c中,如果需要函数的参数具有返回值的能力,往往是通过指针来实现的。比如,实现两整数变量值交换的c程序如下:
void swapint(int *a,int *b)
{
int temp;
temp=*a;
a=*b;
*b=temp;
}
void swapint(int &a,int &b)
{
int temp;
temp=a;
a=b;
b=temp;
}
调用该函数的c++方法为:swapint(x,y); c++自动把x,y的地址作为参数传递给swapint函数。
当大型对象被传递给函数时,使用引用参数可使参数传递效率得到提高,因为引用并不产生对象的副本,也就是参数传递时,对象无须复制。
如果一个函数返回了引用,那么该函数的调用也可以被赋值。
}
int &max(int i, int j) //正确
return m;
}
{
}