-
C++教程之用别名指定名字空间
用别名指定名字空间
名字空间可以一层层嵌套,指定时也得一层层地指定,这样很不方便,一般用 别名代替就方便多了。
#include using namespace std; namespace na { namespace nb { namespace nc { int sum(int
{
a,
int
b)
return
} } } }
a + b;
namespace int
{
A = na::nb::nc;
main ( )
cout << na::nb::nc::sum(5, 11) << endl; cout << A::sum(6, 12) << endl;
return
}
0;
四、没有名字的名字空间
名字空间的名字也可以省略,称之为“无名名字空间”,无名名字空间经常被使 用,其作用是“内部可以引用,而外部不能引用”。
#include using namespace
std;
namespace na { namespace { //无名名字空间 int sum(int a, int b)
{
return
} }
a + b;
int
{
calc(int x,
int
y)
return
} }
sum(x, y);
//内部可以调用无名名字空间的变量或函数
int
{
main ( )
//cout << na::sum(5, 11) << endl; 以外部不能调用
cout << na::calc(6, 12) << endl;
//因为缺少里面的名字,所
return
}
0;
03 章 缺省参数和函数重载
一、参数的缺省值
在 C++中参数可以设置缺省值,设置了缺省值之后,这个参数在调用时可以省 略。注意:设置缺省值的参数只能是最后的几个参数。也就是说某一个参数一旦设 置了缺省值,其后而的参数也必须设置缺省值。例如:f()函数有 3 个参数,如果只 设置第 2 个有缺省值,这就错了。因为调用时只输入 2 个参数时,系统不知道究竟 是第 2 个参数还是第 3 个参数。
#include using namespace std;
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
{ cout << sum() << endl; cout << sum(6) << endl; cout << sum(6, 10) << endl; cout << sum(6, 10, 20) << endl; main ( )
return
}
0;
二、函数的重载
函数的重载在 C++中具有重要作用,重载(overload)不要和后面要学的覆盖 (override)混淆起来。重载是指相同的函数名,但参数的类型或个数中只要有所不同, 便进行再定义,编译之后重载的函数都具有不同的地址,也就是说虽然函数名相同, 实际上是不同的函数,在调用时,编译系统会根据不同之处自动区别是调用哪一个 函数。对于普通函数和后面要学的类的成员函数都适用。 覆盖只对类的构造函数或成员函数适用,是子类继承父类是才使用的非常有用 的功能。重载可以针对运算符,而覆盖不行。上一节中缺省值的设置,实际上在编 译时等价于重载,被生成了 4 个不同的函数。 早期的 C++版本,在定义重载函数时要加上关键字 overload,现在不用了。在 使用重载函数时,如果有类型的自动转换时要特别注意,初学者往往出错在这儿。
#include using namespace std; float fun(float x); double fun(double x); int
{ float f = 132.64; main ( )
double
d = 132.64;
cout << fun(f) << endl; cout << fun(d) << endl;
//cout << fun(5) << endl; 也可转换为 double return
} 0;
//编译错, 参数 5 可以转换为 float,
float
{
fun(float x)
return
}
x / 2.0 ;
double
{
fun(double x)
return
}
x / 3.0;
三、设计时的重载错误
上面的例子中,设计时并没有问题,调用时类型自动转换时发生了二义性。下 面列举的重载函数是设计时就出了问题,二个函数本身就具有重复的意义。
#include using namespace std; int int int
{ fun(int a, fun(int a,
int int
b); &b);
main ( )
int
x=1, y=2;
cout << fun(x, y) << endl;
//这句编译时出错
return
}
0;
int
{
fun(int a,
int
b);
return
a + b;
}
int
{
fun(int a,
int&
b);
return
}
a - b;
上面例子用到了 int&,这叫“引用”,关于什么是“引用”参见下一章。
四、重载函数的地址
本节利用函数指针的方法来取函数的地址,有关函数指针请参考“C 语言教程” 的章节。本节虽没有特别高深内容,但初学者还是跳过为好。
#include using namespace std; void void int
{ space(int count); space(int count,
char
ch);
main ( )
//有一个整型参数的函数指针 void (*fp1)(int); //有一个整型参数、一个字符型参数的函数指针 void (*fp2)(int, char);
fp1 = space; fp2 = space;
//取 space(int)函数的地址 //取 space(int, char)函数的地址 //输出 20 个空格 //输出 20 个等号
fp1(20);
cout << "|" << endl; fp2(20, '=');
cout << "|" << endl;
return
}
0;
//输出 count 个空格字符
void
{
space(int count)
for
}
( ; count; count--) cout << ' ';
//输出 count 个 ch 字符 void space(int count, char
{
ch)
for
( ; count; count--) cout << ch;
04 章 引用
一、独立引用
“引用(reference)”与指针象似但不是指针。 引用主要有 3 种用法: ①单独使用(一 般称为“独立引用”),②作参数使用,③作返回值使用。从功能上来说,引用型变量 又可以看着被引用变量的“别名”, 2 个变量只是名称不同, 这 变量的地址是同一个(共 用体中的元素也是一样)。使用“引用”的好处主要是可以“逆向引用”。 常量也可以被引用,例如:“const int &ref = 10;”,这也是正确的,但这样定义 无任何意义。定义独立引用时需要注意以下规则: 1. 引用型变量在定义时必须初始化。 2. 被引用的对象必须已经分配了空间,即不能为空,或空指针。 3. 被引用的对象不能为地址,即指针变量、数组变量等不能被引用。
#include using namespace std; int
{ main( )
int int
a ; &b = a;
//b 和 a 实际上是同一变量 //b 赋值为 100,也就是 a 赋值为 100
b = 100;
cout << a << endl;
//a 的地址和 b 的地址应该是完全一样
cout << &a << endl; cout << &b << endl;
//▼下面代码有错,注释后才能运行▼int x[] = {12,15,20} ; int &y = x; //错误:数组、指针不能被引用 int int
x1; &y1;
//错误:引用时必须初始化
y1 = x1;
//▲上面代码有错,注释后才能运行▲return
} 0;
二、函数的参数引用 函数的参数引用
许多教程在讲解参数引用时都喜欢选择交换两参数内容的 swap(int &x, int &y) 函数作例子,这的确很容易说明清楚,但并不能说这种用法优于指针作参数。
#include using namespace std; //|右边为指针作参数的代 码,仅作比较用。 void swap(int &x, int &y); int
{ main ( )
int int
i = 12; j = 25; j=" << j << endl;
cout << "i=" << i << "
swap(i, j); cout << "i=" << i << " j=" << j << endl;
return
}
0;
void swap(int &x, int &y)
{
int
t;
//|void swap(int *x, int *y); //| //| //| //| //| //| //| //|swap(&i, &j); //| //| //| //| //| //|void swap(int *x, int *y) //|{ //| int t; //|
t = x; x = y; y = t; }
//| //| //| //|}
t = *x; *x = *y; *y = *x;
三、对象引用作参数
初学者可以先跳过这一节,待学完“类”之后再来看。
#include using namespace std; class
myclass {
int who;
public:
myclass(int n) { who = n; cout << "构造函数调用" << who << endl; } ~myclass() { cout << "析构函数调用" << who << endl; }
int
} };
id() {
return
who;
void
}
f1(myclass o) {
//普通变量方式传递参数
cout << "外部函数调用" << o.id() << endl;
void
}
f2(myclass *o) {
//指针方式传递参数
cout << "外部函数调用" << o->id() << endl;
void
}
f3(myclass &o) {
//引用方式传递参数
cout << "外部函数调用" << o.id() << endl;
int
{
main ( )
myclass x1(1); f1(x1); cout << "" << endl;
myclass x2(2); f2(&x2); cout << "" << endl;
myclass x3(3); f3(x3); cout << "" << endl;
return
}
0;
从上面例子可以看出,用普通变量方式传递参数时,函数首先将参数复制一个 副本,在函数体内使用的是副本。这个副本和参数自身不是同一个地址。而指针方 式和引用方式并不产生副本,函数体内用的真是参数自身。需要注意的是,产生副 本时调用了类的缺省“拷贝构造函数”,这个“拷贝构造函数”并不调用构造函数就产 生了一个副本,有关详细内容参见后面章节。
四、作为函数返回值的引用类型
这一节仍然较深,建议初学者跳过。讲解这一节内容之前,先看下面的程序, 这个程序有没有毛病?
#include using namespace std; int int int
{ f() = 100; cout << x << endl; &f(); x;
main ( )
return
}
0;
int
{
&f()
return
}
x;
许多人都认为第 9 句错了,少数人认为第 4 句可能有问题。事实上,这个程序 完全正确。上面这个函数的返回值是引用类型,通过函数结果的设置反过来去改变 “源头”数据,这种“逆向引用”为 C++增强了很多功能,当然也有许多需要注意的地 方。由于本教程面向初学者,因此到此为止,不再深入下去。
栏目列表
最新更新
C#基于接口设计三层架构Unity篇
C#线程 入门
C#读取静态类常量属性和值
C# 插件式编程
C# 委托与事件有啥区别?
C#队列学习笔记:队列(Queue)和堆栈(Stack
linq 多表分组左连接查询查询统计
C#队列学习笔记:MSMQ入门一
C# 基础知识系列- 1 数据类型
二、C#入门—基础语法
C# 在Word中添加Latex 数学公式和符号
inncheck命令 – 检查语法
基于UDP的服务器端和客户端
再谈UDP和TCP
在socket编程中使用域名
网络数据传输时的大小端问题
socket编程实现文件传输功能
如何优雅地断开TCP连接?
图解TCP四次握手断开连接
详细分析TCP数据的传输过程
SqlServer 利用游标批量更新数据
BOS只读状态修改
SQL Server等待事件—PAGEIOLATCH_EX
数据库多行转换为单一列
获取数据表最后最后访问,修改,更新,
计算经历的时间
SQL查询结果自定义排序
修改数据库默认位置
日期简单加或减
从日期获取年,月或日