指针
1.使用指针最好初始化,这样方式使用未初始化的指针导致系统崩溃 例如 int *p = 0; 或者 int val = 10;int *p = &val;
2.只能把0或者常量0赋值给指针 例如 int zero = 0; int *pi=zero;为错误的 声明应该为const int zero = 0;
3.C++提供了一种特殊懒得指针类型void *,它可以保存任何类型对象的地址
4.指针与引用的区别:1.引用必须初始化2.引用已经初始化,就始终指向同一个特定对象
函数
1.函数指针与指针函数定义区别:
指针函数 int *foo_bar{}
函数指针 typedef bool (*cmpFcn)(const string &,const string &);意思是cmpFcn是一种指向函数的指针类型的名字,它指向返回bool类型并带有const string引用形参的函数的指针
在要使用这种函数指针类型时,值需要直接使用pf即可,不必把整个类型声明全部写出来。
bool lengthCompare(const string &,const string &)等价于 bool (*)(const string &,const string &)
所以cmpFcn pf1 = lengthCompare 与cmpFcn = &lengthCompare等价(直接引用函数名等效于在函数名上应用取地址操作符)
指向函数的指针可用于调用它所指向的函数,可以不需要使用解引用操作符,直接通过指针调用函数
cmpFcn pf = lengthCompare;
lengthCompare("hi","bye");
pf("hi","bye");
(*pf)("hi,"bye");
例如此实例
typedef int (*comFcn)(int &a);
int add(int &a)
{
return ++a;
}
int main() {
int b = 10;
comFcn aa = 0;
aa = &add;
cout<<aa(b)<<endl;
return 0;
}
int add(int &a)
{
return ++a;
}
int main() {
int b = 10;
comFcn aa = 0;
aa = &add;
cout<<aa(b)<<endl;
return 0;
}
函数的形参可以是指向函数的指针
void useBigger(const string &,const string *,bool(const string &,const string &))等价于 void use Bigger(const string&,const string &,bool(*)(const string &,const string &));
例子
int useBigger(const int &aa,const int &bb,int a(int &))
{
int b = 10;
return aa + bb + a(b);
}
typedef int (*comFcn)(int &a);
int add(int &a)
{
return ++a;
}
int main() {
int b = 10;
comFcn aa = 0;
aa = &add;
useBigger(3,4,aa);
cout<<useBigger(3,4,aa)<<endl;
return 0;
}
{
int b = 10;
return aa + bb + a(b);
}
typedef int (*comFcn)(int &a);
int add(int &a)
{
return ++a;
}
int main() {
int b = 10;
comFcn aa = 0;
aa = &add;
useBigger(3,4,aa);
cout<<useBigger(3,4,aa)<<endl;
return 0;
}
返回指向函数的指针 int (*ff(int))(int *,int); 含义是ff返回 int (*)(int *,int *);
等价于 typedef int (*PF)(int *,int);
PF ff(int);
指向重载函数的指针
extern void ff(unsigned int);
void (*pf1)(unsigned int) = &ff;
void (*pf1)(int) = &ff; //错误,没有精确匹配的函数,将导致编译错误。
2.注意使用引用时,函数不能隐式转换
例如
void add(int &a)
{
}
{
}
int main()
{
short val = 10;
add(val);//会报错
return 0;
}
{
short val = 10;
add(val);//会报错
return 0;
}
3.函数通过引用传递数组
例如
void printValues(int (&arr)[10]);//因为[]操作符优先级高,所以必须加()
int main()
{
int k[10] = {0,1,2,3,4,5,6,7,8,9};
printValues(k);
return 0;
}
引用形参限制了可以传递的实参数组,只能使用长度匹配的实参数组来调用函数。当函数需要处理数组且函数体不依赖与数组的长度时应使用指针形参,其他情况下应该使用引用形参
4.sizeof()是C/C++的一个操作符,返回类型为size_t一般定义为typedef unsigned int size_t
5.两种方式在main函数中传递实参(1).主函数形式为int main(){} 在命令行中prog - d -o ofile data0,相当于int main(int argc,char *argc[]){}
(2).直接这样定义主函数int main(int argc,char **argv())
6.atoi(const char *nptr)把一个字符串转换成整数 在头文件stdlib.h中
atof:转换成双精度浮点 atol转换成长整形
ASCⅡ中数字字符值 数字0为48 A为65 a为97
7.return返回时候(1).千万不要返回局部对象的引用,因为函数执行完毕,局部变量占用的存储空间被释放
(2).千万不要返回指向局部对象的指针,一
旦函数结束,返回的指针就变成了指向不再存在的对象的悬垂指针
(3).返回引用的函数返回一个左值
8.定义函数体只能一次,但声明可以多次
9.函数也可以提供默认实参 例如string screenInit(int a = 5) 当提供了实参例如 string screen = screenInit(6),则不使用;当没定义如string screen = screenInit()则使用
,在形参表中,具有默认实参的形参应出现在形参表的末尾
10.static局部对象的作用域在函数内,但是生命期却跨越了这个函数的多次调用(注意作用域和生命期的区别 ,作用域指该名字的程序文本区,生命期指程序执行过程中对象存在的时间)
11.内联函数可以避免函数调用的开销,编译时自动将代码复制。
定义:即在函数前面加inline,内联函数跟一般函数不同,定义必须在头文件中可见,
12.const成员函数(常量成员函数) 例如bool Sales_item::same_isbn(const Sales_item *const this,const Sales_item &rhs)const{ return (this->isbn == rhs.isbn);}
const改变了隐含的this形参的类型。 隐含的this形参将是一个指向total对象的const Sales_Item*类型的指针,由于this是指向const对象的指针,const成员函数不能修改调用该函数的对象,用this时候应该用->不能用.,因为this是指针
14.一般构造函数是放在public部分的,如果为private,这样的类就没有什么用了
15.构造函数的初始化列表例如Sales_item():units_sold(0),revenue(0.0){}在冒号和花括号之间,为类的一个或多个数据成员指定初值
16.一般写C++程序时,将自定义的类放在头文件中,类中成员函数的实现放在.cpp文件中
17.函数重载要求函数声明的返回类型和形参表完全不同,不能仅仅基于不同的返回类型而实现重载
重载确定的三个步骤
例如
void f();
void f(int);
void f(int,int);
void f(double,double = 3.14);
f(5.6);
(1)确定该调用所考虑的重载函数集合,要求:与调用该函数同名,此4个都符合
(2)选择可行函数要求:函数形参个数与调用实参个数相同;每个实参的类型必须与对应形参的类型匹配(可隐式转换)
(3)寻找最佳匹配
含有多个形参的重载确定
例如上面的例子
如果调用f(42,2.56)则出现二义性,解决方法为调用显示的强制类型转换强制函数匹配
f(static_cast<double>(42),2.56)或者f(42,static_cast<int>(2.56))
18.局部函数的声明会屏蔽全局函数,有时导致调用错误
例如
void print(const string &);
void fooBar(int ival)
{
void print(int);
print("Value");//调用错误
}