4.指针函数和函数指针
指针函数:返回地址值的函数
函数指针:指向函数的入口地址的指针.
格式:<存储类> <数据类型> (*函数指针名)(参数表) [=函数名];
(auto) int (* fun)(int,int);
使用例子:
#include<iostream.h>
void fun(int a,int b);
void (*pfun)(int,int)=fun;
void main()
{
(*pfun)(2,4);//equal to cout<<a<<" and "<<b<<endl;
}
void fun(int a,int b)
{
cout<<a<<" and "<<b<<endl;
}
另一个例子:
int Add(int op1,int op2){return(op1+op2);}
int Sub(int op1,int op2){return(op1-op2);}
int (Math*)(int,int);//define a function pointer
Math=Add;
Int rusult = Math(1,2);//this really calls Add(1,2)
Math=Sub;
Int rustult = Math(1,2);//this really calls Sub(1,2)
5.C++发展简史
1979年,Bjarne Stroustrup在位于新泽西州的贝尔实验室中发明了C++,最初他把这种语言命名为“带类的C语言”。在1983年12月Bjarne Stroustrup采纳Rick Mascitti的建议,将其发明的新语言命名为“C++”之前,人们一直用“带类的C(C with Classes)”来称呼这种脱胎于C语言的,带有数据抽象机制的“方言”。
Stroustrup从Simula语言借用了类、派生、访问控制等面向对象概念.
如果说C++语言的生身父母分别是C语言和Simula语言的话,那么,1984年出现的,借助操作符重载实现的I/O流技术就是C++这个幼童甩开父母的庇护,向新的代码风格迈出的第一步了.
Stroustrup于1988年首次公布了与模板(template)有关的语法设计. 模板的概念来自Clu语言,并综合了Smalltalk和Ada语言中相关技术的优点
1998年,在ANSI/ISO标准化委员会的支持下,STL被作为标准C++库(Standard C++ Library)的一部分收入了C++国际标准之中。
1990年以后,ANSI/ISO的C++标准化委员会才将包括Stroustrup在内的大批专家以及包括Apple、Borland、DECHP、IBM、Microsoft、Sun、Unisys在内的知名公司召集在一起,像所有国家的议会或人民代表大会一样通过没完没了的会议、讨论和投票制定C++的国际标准。标准直到1998年9月才正式发布。在国际标准化组织的档案库里,C++标准的代号是ISO/IEC 14882:1998
C++中引入.NET技术后,又有了新的变化,C++也有了垃圾回收功能了-_-!
6.关于表态变量:static
在一个函数内,以下两种置初值的方法有所区别:
static int cout=0;
和static int cout;
cout=0;
区别在于:前者仅在第一次调用此函数时被初始化为0,后者则是每次调用此函数时都先初始化为0.
7.关于inline
inline是把函数声明为内联函数.
好处:
首先,函数调用涉及到参数的出入栈操作,消耗一定的空间和时间.为了避免这种情况,可以把该函数声明为inline,则当编译的时候,编译器先将该函数生成一段代码,再把它插到所有调用到该函数的地方,可以加快程序的执行速度,所以如果一个函数需要执行多次(成千上万),则可以把它声明为inline.不过这里要注意一点的就是,内联函数里面不能有复杂的结构如循环,分支等,只能是简单的语句,否则声明inline会造成反效果.
inline和宏定义有时是差不多效果的,具体编译器具体分析.
使用inline会使最终的目标代码文件(.obj)变大,因为那些inline函数都被编译器扩展了.
8.关于<<符号
如果有以下模板实例的声明: Chain<int,Node<int>> m_chain;
因为最新C++标准里面”>>”符号会被认为是输入流操作符,编译出错!!所以上面的声明应该改为: Chain< int,Node<int> > m_chain; 注意两边留出一个空格啊!
9.对象的生存周期问题
创建对象一般有两种方式:
(1).在栈中定义对象,其一般格式如下:
类名 对象名 (参数表);
栈中对象的特点:当程序执行超出栈中类对象的作用域时(即在该对象的生存期终止时) 它们会自动被调用其相应的析构函数来释放其对应对象所占的内存区及处理其它善后事务。
(2).在堆中申请对象(在自由存储区中分配对象),其一般格式如下:
类名* 类指针名 = new 类名 (参数表);
堆中对象的特点:一旦对象在堆中创建,程序执行过程中除非使用delete等操作符来取消该对象,否则该对象将一直生存下去。操作符delete使用格式如下:
delete 类指针名;
执行该语句的作用是释放该指针所指对象所占的自由存储区。若此对象的类有一个已定义的析构函数,delete操作符会调用它来做析构函数所要做的事情:释放对应对象所占自由存储区、处理善后事务;否则delete操作符会调用编译器为该函数自动生成的析构函数来释放
自由存储区。
10.一些要注意地方(比较偏的知识)(摘自<<C++语言命令详解(第二版)>>)
(1)wchar_t (长字符)类型
该数据类型是整形数类型的一种,它用来存储那些双字节而不是单字节字符.较长的字节数可以支持在应用程序的国际发布版本里所使用的扩展字符集(如常用的Unicode字符集).
因为字符串是char类型的数组,所以对wchar_t类型字符串的初始化不像对普通字符串初始化那样简单.下面是wchar_t类型字符中的初始化操作:
wchar_t wstr[10];
wstr[0]=’T’;
wstr[0]=’h’;
wstr[0]=’e’;
最好还是编写一个函数简化相应的初始化操作.
(2)sizeof(计算数据结构的字节长度)
sizeof(表达式)
sizeof(类型名)
(3)typeid(获得类型信息)
typeid运算符根据运行时类型信息(RTTI)来决定其操作数在程序运行时刻的类型.在编程中我们不常使用typeid运算符,这是因为在绝大多数情况下程序员都清楚自己所使用的数据类型.尽管如此,typeid运算符在某些情况下还是有一定作用的.例如,如果某一表达式非常复杂而你又想要确定它的返回值类型,就可以使用typeid语句.
Typeid运算符经常在指向某一对象的指针里使用.当某一类具有多态特性时,即它的基类包含至少一个虚函数,使用typeid运算符就可以得到对象所指的实际类型.typeid运算符的语法表达式为:#include<typeinfo.h> typeid(expression | type)
(4)类型转换操作符
type:老版本的数据类型转换 (type)expr或type(expr)
const_cast:去除变量的const或volatile属性;这使你能够将一个const型指针传递到一个非const型的参数
dynamic_cast:在程序运行时,核实一个对象所指向的是不是一个明确的类型.如果不是则不能转换,抛出bad_cast类型的异常。使用方法:dynamic_cast<type> (expr)
reinterpret_cast:在不相关的两个指针类型之间进行类型转换,它使你能将void *类型的指针转换为某一特定类型.也可以把指针强制转换为一个整数。
static_cast:在相关的指针类型或对象之间进行类型转换,当将一个长度较大的类型转换为一个较小的类型时,可以使用这个类型转换符来制止编译器发出警告.它是用来替代传统形式的强制转换运算符。