C++面试总结
1、多态
C++多态分两种--静态和动态,其中静态联编支持的多态称为编译时多态,包括重载和模板;动态联编支持的多态称为运行时多态,包括
继承和虚函数实现。
多态主要是由虚函数实现的,虚函数允许子类重新定义基类的虚函数(override);重载(overload)则是一个类中有多个同名函数,这些函数的参数列
表不同(参数类型、个数)。
多态的目的是为了接口重用:不论传递过来的是哪个类的对象,都能通过同一个接口调用到适应各自对象的实现办法。
最常用的方法就是声明基类的指针,利用该指针指向子类对象,调用相应的虚函数,可以根据指向子类的不同而调用不同的虚函数。
2.四种类型转换
static_cast:基本数据类型转换(int->float);类层次结构中上行转换(派生类转为基类),下行转换不安全。
dynamic_cast:类层次间的上、下行转换,都是安全的,下行转换会检查被转换的类(基类)是否有虚函数,有虚函数才合法。
reinterpret_cast:将一个类型的指针转为另一个类型的指针。
const_cast:把const类型的指针转为非const类型的指针。
3.运算符重载
单目声明为成员函数,多目声明为友元。
重载流插入和流提取运算符:istream& operator >>(istream&,自定义类&),只能定义为友元或普通函数。
4、内存对齐原则
1.数据成员对齐规则:struct, union的数据成员,第一个数据成员放在offset为0的地方,之后的数据成员的存储起始位置都是放在该数据成员大小的整数倍位置。如在32bit的机器上,
int的大小为4,因此int存储的位置都是4的整数倍的位置开始存储。
2.结构体作为数据成员的对齐规则:在一个struct中包含另一个struct,内部struct应该以它的最大数据成员大小的整数倍开始存储。如 struct A 中包含 struct B, struct B 中包含数据
成员 char, int, double,则 struct B 应该以sizeof(double)=8的整数倍为起始地址。
3.收尾工作的对齐规则:整个struct的大小,应该为最大数据成员大小的整数倍。
5、模板实现
函数模板:
template<typename T 或 class T>
T max(T a, T b ,T c)
类模板:
template<typename T> class 类名{
}
6、指针和const
指向常量的指针:不能用于改变所指常量的值
const double pi = 3.14
const double *cptr = π
常量指针:指针本身为常量(指针为对象,引用不是,所以没有常量引用),必须初始化且指针中的地址不能再改变。
int errNum = 0;
int * const curErr = &errNum;
指向常量的常量指针:既不能修改指向的对象,也不能修改只想对象的值
7、虚函数
C++的虚函数主要作用是“运行时多态”,父类中提供虚函数的实现,为子类提供默认的函数实现。子类可以重写父类的虚函数实现子类的特殊化。
C++中包含纯虚函数的类,被称为是“抽象类”。抽象类不能使用new出对象,只有实现了这个纯虚函数的子类才能new出对象。C++中的纯虚函数更像是“只提供申明,没有实现”,是对子类的约束,是“接口继承”。纯虚函数无函数体:viutual float area()const=0;
基类的析构函数要定义为虚函数,防止delete基类指针时,只调用基类的析构函数而不执行派生类的析构函数。
8、内联函数
执行普通函数时,程序会先进行入栈保护,转到函数位置执行函数,然后再返回。需要一定的开销。
程序无需跳到另外一个位置执行代码,使用函数代码替换函数调用,调用快,无需内存开销。
宏:内联代码的参数是按值传递的,宏是通过文本替换。
区别:
(1)内联函数在编译时展开,宏在预编译时展开;
(2)内联函数直接嵌入到目标代码中,宏是简单的做文本替换;
(3)内联函数有类型检测、语法判断等功能,而宏没有;
(4)inline函数是函数,宏不是;
(5)宏定义时要注意书写(参数要括起来)否则容易出现歧义,内联函数不会产生歧义;
9、typedef
四种用途(主要是为了定义别名),参考:http://www.cnblogs.com/charley_yang/archive/2010/12/15/1907384.html
关于和define的区别,参考:http://www.cnblogs.com/kerwinshaw/archive/2009/02/02/1382428.html
10、静态数据成员和静态成员函数
静态数据成员被当作类的成员,在程序中只有一份拷贝,只分配一次内存,由该类的所有对象共享访问,对每个对象的值都一样。
定义时要分配空间,所以不能在类声明中定义。
属于类,不能访问类对象的非静态数据成员,也无法访问非静态成员函数,只能调用其余的静态函数。
11、模版特化
针对特殊的类型,需要进行特殊处理。参考这篇博客给的例子:http://www.cnblogs.com/hicjiajia/archive/2010/08/27/1810372.html
12、explicit关键字
在C++中, 如果的构造函数只有一个参数时, 那么在编译的时候就会有一个缺省的转换操作:将该构造函数对应数据类型的数据转换为该类对象。加入explicit是为了
防止类构造函数的隐式自动转换,只对有一个参数的构造函数有效(参数个数大于等于2时不会发生隐式转换);或除了第一个参数外,其他参数都有默认值时同样有效。
具体便子可参考:http://www.cnblogs.com/ymy124/p/3632634.html
13、new/delete、malloc/free之间的区别
1、new、delete是c++中的操作符,malloc、free是C中的一个库函数,它们都可用于申请动态内存和释放内存。
2、new 不止是分配内存,而且会调用类的构造函数,同理delete会调用类的析构函数,而malloc则只分配内存,不会进行初始化类成员的工作,同样free也不会调用析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。
14、为什么要用static_cast转换而不用c语言中的转换
C中强制转换编译时不同类型(比如完全不同的两个类)也可通过,但static_cast不能通过,多了编译时的类型检查,更安全。
15、异常机制
try catch throw
16、c++ 必须在构造函数初始化表里进行初始化的数据成员有哪些
常量成员、引用类型、没有默认构造函数的类类型(只能用拷贝构造函数)
17、auto_ptr
就是动态分配对象以及当对象不再需要时自动执行清理
具体参考:http://www.cnblogs.com/bizhu/archive/2012/07/29/2614355.html
18、extern "C"
参考:http://blog.csdn.net/jiqiren007/article/details/5933599