//学习 《Visual+C++从入门到精通第三版》与《面向对象程序设计与Visual C++6.0教程》
面向过程程序设计
函数
int GetMax(int x,int y,int z=0) 默认值参数== ==不能出现在非默认值的左边
定义数组参数时,可以不指定大小。(C++编译器传递的是数组的首地址) void Sort (int array[],int len)-------合法 ?如何限制函数调用时必须传递指定长度的数组? 使用数组的引用作为函数的参数,这时数组的长度将作为参数的一部分
void Sort (int (&array)[10])
{
int itemp=0;
for (int i=0;i<10;i++)
{
for (int j=0;j<10;j++)
{
if (array[i]>array[j]+1)
{
itemp=array[i];
array[i]=array[j];
array[j]=itemp;
}
}
}
printf("排序之后:");
for (int i=0;i<10;i++)
printf("%4d",array[i]);
}
参数为数组、指针或引用类型 | 引用传递方式(修改参数会影响到原本变量的值 |
---|
其他情况 | 值传递方式(修改参数不影响原有参数) |
| 传值调用 | 传地址调用 | 引用调用 |
---|
主函数 | swap(x,y) | swap(&x,&y) | swap(x,y) | 调用函数 | void swap(int a,int b) | void swap(int *a,int *b) | void swap(int &a,int &b) | 实质 | 形参的变化与实参无关 | 通过形参指针对实参进行间接读写 | 被调用函数使用实参的别名,改变形参实质上是在改变实参 |
内联函数
- 适用于简单且调用频繁的函数
- 空间换时间的方法
- 添加了inline关键字声明的内联函数是对编译器的一个建议,并非强制执行。对于微软的C++编译器可以使用_forceinline 关键字强制执行
inline 返回值类型 函数名(形参) { …… }
重载函数
- 多个函数具有相同的函数名称
- 编译器依靠参数类型或参数个数不同来区分调用哪个函数
- 函数的返回值类型并不作为区分重载函数的一部分
- 当参数类型为指针或引用类型,const关键字将作为重载函数的标识,其他参数类型不行
bool Validate(const int *x)
{
return (*x>0)?1:0;
}
bool Validate(int *x)
{
return (*x>0)?1:0;
- typedef(用typedef定义的与原有类型相同时) 、参数的默认值不作为区分重载函数的标识
- 局部域中声明的函数将隐藏而不是重载全局域中的函数
bool Validate(float x)
{……}
bool Validate(int x)
{……}
int main(int argc,char*argc[])
{
bool Validate(double x);
validate(10.5f);
return 0;
}
bool Validate(double x,double y)
{……}
函数指针 == ==
- C++中,函数名实际上是指向函数的指针
- 函数指针指向的函数必须与函数指针定义的函数形式相同
typedef int (*ptfun)(int ,int );
int invoke(int x,int y,ptfun fun)
{ return fun(x,y);}
int sum(int x,int y){return x+y;}
int sub(int x,int y){return x-y;}
int mul(int x,int y){return x*y;}
int divi(int x,int y){return x/y;}
int main(int argc,char*argv[])
{
ptfun pfun;
ptfun=sum;
int ret =inveke(20,10,pfun);
pfun =mul;
ret =invoke(20,10,pfun);
return 0;
}
typedef的详细用法
- 相同名称的内部变量会隐藏外层局部作用域中的变量,访问全局变量要使用"::"
- 对于全局变量默认值为0,局部变量其值不可预见
命名空间
namespace 名称 { 常量、变量、函数等对象的定义 }
namespace Output
{
const int MAXLEN=128;
int ivar=10;
void PutoutText(const char* dchData)
{
if (pchData!=NULL)
{
printf("PutoutText 命名空间: %s\n",pchData);
}
}
}
Output::PutoutText("Welcome to China");
using namespace Output;
(访问Output命名空间中的函数)
-对于命名空间的五点补充
- 同一个命名空间,可以在多个文件中进行不同的定义,此时命名空间中的内容为所有文件中此命名空间内容的总和(所以在不同文件的同一空间中也不能出现相同名称的变量)
- 命名空间可嵌套
namespace Windows
{
……
namespace GDI
{
void WriteText(const char*pchMag)
{……}
……
}
}
Windows::GDI::WriteText("2008");
using namespace Windows::GDI;
WriteText("2008");
- 函数中定义的局部变量与命名空间中的变量同名时,命名空间中的变量将被隐藏。
如果想要访问被隐藏的命名空间中的变量,需使用命名空间作为前缀,如“Output::ivar"(尽管前文已经使用using 命令引用命名空间Output
4.引用多个命名空间中存在的相同名字的函数时会出现编译错误,此时使用具体命名空间进行区分,如:Windows::PutoutText(“Welcome to China”) 5. 可以定义未命名命名空间,此时其仅适用于当前文件且其中对象不能与全局对象完全相同(可以重载)
函数模板
template type Sum (type svar,type yvar) { return xvar+yvar; }
class也可用typedef代替 type是用户定义的标识符,也可以是其他标识符 调用时 :
int ans=Sum(10 ,20 );//10,20的数据类型与int一致 double ans=Sum(10.2 ,10.3 )//10.2,10.3的数据类型与double 一致 int ans=Sum<int >(10.5 ,20 );//正确调用,认为是两个int类型数相加
一个含有模板非类型参数,模板类型参数的例子
template <class type,int len>
type Max (type array[len])
{
type ret =array[0];
for (int i=1;i<len;i++)
ret =(ret>array[i]?ret:array[i];
return ret;
}
int array[5]={1,2,3,4,5};
int iret =Max<int,5>(array);
double dset[3]={10.5,11.2,9.8};
double dret =Max<double,3>(dset);
函数模板重载的例子
template<class type>
type Sum(type xvar,type yvar)
{return xvar+yvar;}
template<class type>
type Sum(type array[],int len)
{
type ret =0;
for (int i=0;i<len;i++)
ret+=array[i];
return ret;
}
int main(int argc,char*argv[])
{
int iret =Sum(10,20);
printf("整数之和:%d\n",iret);
int array[5]={1,2,3,4,5};
int ret=Sum(array,5);
printf("数组元素之和:%d\n",ret);
return 0;
}
编译预处理
- 宏定义
#define #undef - 文件包含指令
#include<系统头文件> #include"文件名" - 条件编译
#if 常量表达式1
程序段1
#elif 常量表达式2
程序段2
……
#else
程序段n+1
#endif
如果标识符被#define定义,且没有执行undef语句,则编译程序段1,否则编译程序段2,else 可省略
#ifdef 标识符
程序段1
#else
程序段2
#endif
#如果标识符没有被定义,编译程序段1,否则编译程序段2,else 可省略
#ifndef 标识符
程序段1
#else
程序段2
#endif
|