十八万字整理C/C++、嵌入式软开 常见面试题汇总12
十八万字吐血整理的C/C++、嵌入式常见面试题!!!!
文中很多资料避免不了从网上或是其他复习资料里收集整理,十分感谢前辈的辛勤付出,如果存在侵权请一定联系我进行删除。
系列文章PDF下载地址:《最全C_C++及嵌入式软开面试题宝典.pdf》
61、虚函数的代价?
1.带有虚函数的类,每一个类会产生一个虚函数表,用来存储指向虚成员函数的指针,增大类;
2.带有虚函数的类的每一个对象,都会有一个指向虚表的指针,会增加对象的空间大小;
3.不能再是内联的函数,因为内联函数在编译阶段进行替代,而虚函数表示等待,在运行阶段才能确定到底是采用哪种函数,虚函数不能是内联函数。
62、用C语言实现C++的继承
#include <iostream> using namespace std; //C++中的继承与多态 struct A { virtual void fun() //C++中的多态:通过虚函数实现 { cout<<"A:fun()"<<endl; } int a; }; struct B:public A //C++中的继承:B类公有继承A类 { virtual void fun() //C++中的多态:通过虚函数实现(子类的关键字virtual可加可不加) { cout<<"B:fun()"<<endl; } int b; }; //C语言模拟C++的继承与多态 typedef void (*FUN)(); //定义一个函数指针来实现对成员函数的继承 struct _A //父类 { FUN _fun; //由于C语言中结构体不能包含函数,故只能用函数指针在外面实现 int _a; }; struct _B //子类 { _A _a_; //在子类中定义一个基类的对象即可实现对父类的继承 int _b; }; void _fA() //父类的同名函数 { printf("_A:_fun()\n"); } void _fB() //子类的同名函数 { printf("_B:_fun()\n"); } void Test() { //测试C++中的继承与多态 A a; //定义一个父类对象a B b; //定义一个子类对象b A* p1 = &a; //定义一个父类指针指向父类的对象 p1->fun(); //调用父类的同名函数 p1 = &b; //让父类指针指向子类的对象 p1->fun(); //调用子类的同名函数 //C语言模拟继承与多态的测试 _A _a; //定义一个父类对象_a _B _b; //定义一个子类对象_b _a._fun = _fA; //父类的对象调用父类的同名函数 _b._a_._fun = _fB; //子类的对象调用子类的同名函数 _A* p2 = &_a; //定义一个父类指针指向父类的对象 p2->_fun(); //调用父类的同名函数 p2 = (_A*)&_b; //让父类指针指向子类的对象,由于类型不匹配所以要进行强转 p2->_fun(); //调用子类的同名函数 }
63、继承机制中对象之间如何转换?指针和引用之间如何转换?
1.向上类型转换
将派生类指针或引用转换为基类的指针或引用被称为向上类型转换,向上类型转换会自动进行,而且向上类型转换是安全的。
2.向下类型转换
将基类指针或引用转换为派生类指针或引用被称为向下类型转换,向下类型转换不会自动进行,因为一个基类对应几个派生类,所以向下类型转换时不知道对应哪个派生类,所以在向下类型转换时必须加动态类型识别技术。RTTI技术,用dynamic_cast进行向下类型转换。
64、C++四种类型转换
C++的四种强制转换包括:static_cast, dynamic_cast, const_cast, reinterpret_cast。
1.static_cast能进行基础类型之间的转换,也是最常看到的类型转换。明确指出类型转换,⼀般建议将隐式转换都替换成显示转换,因为没有动态类型检查,上⾏转换(派⽣类->基类)安全,下⾏转换(基类->派⽣类) 不安全,所以主要执⾏⾮多态的转换操作;
它主要有如下几种用法:
- 用于类层次结构中父类和子类之间指针或引用的转换。进行上行转换(把子类的指针或引用转换成父类表示)是安全的;
- 进行下行转换(把父类指针或引用转换成子类指针或引用)时,由于没有动态类型检查,所以是不安全的;
- 用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。
- 把void指针转换成目标类型的指针(不安全!!)
- 把任何类型的表达式转换成void类型。
2.const_cast专⻔⽤于const,volatile属性的转换,去除const性质,或增加const性质,是四个转换符中唯⼀⼀个可以操作常量的转换符。除了去掉const 或volatile修饰之外,type_id和expression得到的类型是一样的。但需要特别注意的是const_cast不是用于去除变量的常量性,而是去除指向常数对象的指针或引用的常量性,其去除常量性的对象必须为指针或引用。
3.reinterpret_cast不到万不得已,不要使⽤这个转换符,⾼危操作。使⽤特点:从底层对数据进⾏重新解释,依赖具体的平台,可移植性差。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,在把该整数转换成原类型的指针,还可以得到原先的指针值)。可以在指针和引⽤之间进⾏肆⽆忌惮的转换。
4.dynamic_cast 专⻔⽤于派⽣类之间的转换,type-id必须是类指针,类引⽤或void*,主要用在继承体系中的安全向下转型。它能安全地将指向基类的指针转型为指向子类的指针或引用,并获知转型动作成功是否。当类型不⼀致时,转型失败会返回null(转型对象为指针时)或抛出异常bad_cast(转型对象为引用时),⽽static_cast,当类型不⼀致时,转换过来的事错误意义的指针,可能造成⾮法访问等问题。dynamic_cast 会动用运行时信息(RTTI)来进行类型安全检查,因此 dynamic_cast 存在一定的效率损失。当使用dynamic_cast时,该类型必须含有虚函数,这是因为dynamic_cast使用了存储在VTABLE中的信息来判断实际的类型,RTTI运行时类型识别用于判断类型。typeid表达式的形式是typeid(e),typeid操作的结果是一个常量对象的引用,该对象的类型是type_info或type_info的派生。
65、为什么要用static_cast转换而不用c语言中的转换?
1.更加安全;
2.更直接明显,能够一眼看出是什么类型转换为什么类型,容易找出程序中的错误;可清楚地辨别代码中每个显式的强制转;可读性更好,能体现程序员的意图
目前已整理十万字的C/C++、嵌入式常见面试题!!!!还在持续更新中!!! 这个专栏写完了,再po上自己亲手敲的笔试编程题整理。