第五章的表达式和第六章的语句我就没有仔细看了,本来也想着跳过函数这一章直接进入IO库的,后来发现里面有一节是关于函数指针的,想着当时看《C专家编程》的时候好像还是觉得有些难懂,于是就看了,这一看,其实发现有很多知识点以前不清晰的,或者是记不住的,原来背后是有很多道理的啊。主要就是有关const的,还有就是函数的指针了。这个const真的是大有学问啊。
1. const与函数的各种关系
从前我写函数,很害怕使用const的,因为总会编译不通过,最后我就“放宽限制”,全部都不用const啦。可以见得我以前是多么地急功近利,都不愿意花个功夫好好研究一下const的意义的。当然,通过《C专家编程》和这两天的阅读,我对const与指针、引用的关系也渐渐清晰了。
const与函数的关系首先表现在形参上,对函数的形参加上const限制,说明函数在使用这个形参的时候不可以改变它。但是,必须注意到的是,普通的形参(非引用)传递给函数时,实际上是复制了一个副本,因此有(1)调用函数时,如果该函数使用非引用的非const形参,则既可以给该函数传递const实参,也可以传递非const实参。反之,(2)如果函数将形参定义为非引用的const类型,传递给函数的实参即可以是const的,也可以是非const的。
道理说清楚了,实际上一点也不混乱,重点就是,对函数的形参加上const限制,说明的是函数在使用这个参数的时候不可以改变的,而实参传递给函数时,实际上传的是它的副本。这两点搞清楚了,就很清晰了。
除了非引用的形参,还有引用形参,引用实参的作用在于,当我们需要通过函数对实参做出修改(而不仅仅是利用它的值)时,需要用引用形参;另一方面,假设实参很大,我们不希望发生复制,也会直接使用引用形参,这个时候,如果我们不希望对实参发生改动,则必须将该引用形参设成const的。书中有一句话是这样说的:“应该将不修改相应实参的形参定义为const引用。如果将这样的形参定义为非const引用,则毫无必要地限制了该函数的使用。”这就是为什么我前面在“放宽限制”那里加了引号,实际上,如果考虑到函数不一定是你自己一个人使用的,使用const对函数形参进行限制,实际上加大了它可接受的参数范围(如前所述,实参既可以是const的,也可以是非const的,而如果没有const限制,实参就不能为const的)。举书里的一个例子:
//returns index of first occurrence of c in s or s.size() if c isn't in s
//Note: s doesn't change, so it should be a reference to const
string::size_type find_char( string &s, char c ){
string::size_type i = 0;
while( i!= s.size() && s[i] != c )
++i;
return i;
}
这个时候,首先被限制的就是字符串常量值,虽然字符串常量值可以转换为string对象,但像这样的调用:
if( find_char( "Hello world!", 'c' ) )
将会导致编译失败。
另外,如果string在外面被声明成const的,我们也无法使用此函数去检测string中的字符了。所以说这样限制了函数的使用。
const与函数的另一个关系表面在类的const成员函数上。设类:
class Sales_item{
public:
double avg_price() const;
bool same_isbn( const Sales_item &rhs ) const
{ return isbn == rhs.isbn; }
private:
std::string isbn;
unsigned units_sold;
double revenue;
}
之前c++没有好好学,我一直不知道avg_price()和same_isbn(...)函数后面加个const到底是指什么。原来,const改变了隐含的this形参的类型。我们知道每个成员函数都有一个额外的、隐含的形参this,在调用成员函数时,形参this初始化为调用函数的对象的地址。而这个const改变了隐含的this的形参的类型,表示指向const Sales_item*类型的指针。
用这种方式使用const的函数称为常量成员函数,由于this是指向const对象的指针,const成员函数不能修改调用它们的对象的数据成员。
“const对象、指向const对象的指针或引用只能用于调用其const成员函数”,这句话同样提醒我们,如果函数确实不需要对this对象做出修改,应该声明它为const成员函数,不然其使用范围又是被人为地限制了。
2. 指向函数的指针
奇怪的是,现在再看指向函数的指针,我却没有觉得有那么难理解了。应该是对声明的分析更熟悉了。反正先把名字找出来,然后把与它关联的优先级最高的拿出来,然后就大概知道这个声明是指的什么了。具体可以看这篇http://philoscience.iteye.com/blog/998208(分析C语言的声明)
http://philoscience.iteye.com/category/176811