一、extern "C"的作用

void foo(int x, int y);

foo函数被C编译器编译后在库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字用来支持函数重载和类型安全连接。由于编译后的名字不同,C++程序不能直接调用C函数。C++提供了一个C连接交换指定符号extern "C"来解决这个问题。

extern "C"

{

void foo(intx, int y);

}

这就告诉C++编译器,foo是个C连接,应该到库中找名字_foo而不是找_foo_int_int。

 

二、隐式类型转换导致重载函数产生二义性

void output(int x);

void output(float x);

void main()

{

output(0.5);

}

结果:编译错误,因为数字本身没有类型,编译器不知道该将0.5转换成int还是float。

 

三、成员函数的重载、覆盖与隐藏

成员函数被重载的特征:

(1)相同的范围(在同一个类中);

(2)函数名相同;

(3)参数不同;

(4)virtual关键字可有可无。

覆盖是指派生类函数覆盖基类函数,特征是:

(1)不同的范围(分别位于派生类与基类);

(2)函数名相同;

(3)参数相同;

(4)基类函数必须有virtual关键字。

隐藏是指派生类的函数屏蔽了与其同名的基类函数,规则如下:

(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数被隐藏(不是重载)。

(2)如果派生类的函数与基类的函数同名,并且参数不同,但是基类没有virtual关键字。此时,基类的函数被隐藏(不是覆盖)。

 

三、参数的缺省值

缺省值只能出现在函数的声明中,而不能出现在定义体中。

 

四、运算符重载

Complex operator +(const Complex &a, const Complex &b);

如果运算符被重载为全局函数,那么只有一个参数的运算符叫做一元运算符,二元运算符只有一个右侧参数,因为对象自己成了左侧参数。

如果运算符被重载为类的成员函数,那么一元运算符没有参数,二元运算符只有一个右侧参数,因为对象自己成了左侧参数。

建议将运算符重载为成员函数,= () [] ->只能被重载为成员函数。

 

不能被重载的运算符:

(1)不能改变C++内部数据类型(如int,float等)的运算符。

(2)不能重载'.',因为'.'在类中对任何成员都有意义,已经成为标准用法。

(3)不能重载目前C++运算符集合中没有的符号,如#,@,$等。一是难以理解,二是难以确定优先级。

(4)对已经存在的运算符进行重载时,不能改变优先级规则,否则引起混乱。

 

五、函数内联

用内联取代宏,因为内联能避免宏替代时候的一些错误,能进行类型安全检查,或者是自动类型转换,能操作类的私有成员。

在C++程序中,应该用内联取代宏,"断言assert”是唯一的例外。为了不在程序的Debug版本和Release版本引起差异,assert不应该引起任何副作用。如果assert是函数,由于函数调用会引起内存、代码的变动,那么将导致Debug版本与Release版本存在差异。所以assert不是函数,而是宏。

inline必须放在函数定义体前,才起作用。inline void Foo();

定义在类声明之中的成员函数将自动地成为内联函数。

内联会复制代码,使程序的总代码量增大,消耗更多的内存空间。

posted on 2013-03-17 20:42  guoxiang  阅读(286)  评论(1编辑  收藏  举报