C方向讲解.docx
《C方向讲解.docx》由会员分享,可在线阅读,更多相关《C方向讲解.docx(7页珍藏版)》请在冰豆网上搜索。
C方向讲解
1、简单题
(1)为什么拷贝构造函数Account(constAccout&other)不能写成Account(constAccoutother)。
答案:
如果不传入引用,函数传参过程中系统会调用一次复制操作,也就是会调用一次拷贝构造函数,而该拷贝构造函数又是参数传递,就会继续调用拷贝复制(拷贝构造),这样就会进入一个死循环。
(2)C++拷贝构造函数深拷贝与浅拷贝区别。
答:
浅拷贝和深拷贝主要区别就是复制指针时是否重新创建内存空间。
如果没有创建内存只赋值地址为浅拷贝;
创建新内存把值全部拷贝一份就是深拷贝;
浅拷贝在类里面有指针成员的情况下只会复制指针的地址,会导致两个成员指针指向同一块内存,这样在要是分别delete释放时就会出现问题,因此需要用深拷贝。
(3)什么是“引用”?
声明和使用“引用”要注意哪些问题?
答:
引用就是某个目标变量的“别名”(alias),对应用的操作与对变量直接操作效果完全相同。
申明一个引用的时候,切记要对其进行初始化。
引用声明完毕后,相当于目标变量名有两个名称,即该目标原名称和引用名,不能再把该引用名作为其他变量名的别名。
声明一个引用,不是新定义了一个变量,它只表示该引用名是目标变量名的一个别名,它本身不是一种数据类型,因此引用本身不占存储单元,系统也不给引用分配存储单元。
不能建立数组的引用。
(4)C++中的空类,默认产生哪些类成员函数?
答案:
构造函数、拷贝构造函数、析构函数、赋值运算符、取址运算符、const取址运算符。
利用如下程序段解析:
class Empty {
public:
Empty(); //缺省构造函数
Empty(const Empty &); //拷贝构造函数
~Empty(); //析构函数
Empty & operator=(const Empty &); //赋值运算符
Empty* operator&(); //取址运算符
const Empty* operator&() const; //取址运算符
};
(5)多态的作用?
主要是两个:
1.隐藏实现细节,使得代码能够模块化;扩展代码模块,实现代码重用;
2.接口重用:
为了类在继承和派生的时候,保证使用家族中任一类的实例的某一属性时的正确调用。
(6)类成员函数的重载、覆盖和隐藏区别?
答案:
a.成员函数被重载的特征:
1)相同的范围(在同一个类中);
2)函数名字相同;
3)参数不同;
4)virtual关键字可有可无。
b.覆盖是指派生类函数覆盖基类函数,特征是:
1)不同的范围(分别位于派生类与基类);
2)函数名字相同;
3)参数相同;
4)基类函数必须有virtual关键字。
c.“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下:
1)如果派生类的函数与基类的函数同名,但是参数不同。
此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。
2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。
此时,基类的函数被隐藏(注意别与覆盖混淆)。
(7)在C++程序中调用被C编译器编译后的函数,为什么要加extern"C"?
答:
C++语言支持函数重载,C语言不支持函数重载。
函数被C++编译后在库中的名字与C语言的不同。
假设某个函数的原型为:
voidfoo(intx,inty);该函数被C编译器编译后在库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字。
C++提供了C连接交换指定符号extern"C"来解决名字匹配问题。
(8)面向对象程序设计的优点?
答:
开发时间短,效率高,可靠性高。
面向对象编程的编码具有高可重用性,可以在应用程序中大量采用成熟的类库(如STL),从而虽短了开发时间,软件易于维护和升级。
(9)什么是单例模式?
保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。
(10)构造和析构的次序
答:
1.构造顺序:
构造虚基类->构造基类(从左到右)->初始化列表->构造函数体。
2.析构顺序:
(与构造顺序完全相反)
析构函数体->清除成员变量->析构基类部分(从右到左)->析构虚基类部分。
(11)C++中new-delete与malloc-free的区别!
答:
new建立的是一个对象;malloc分配的是一块内存.
详细如下:
1.malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。
它们都可用于申请动态内存和释放内存
2.对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。
对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。
由malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。
3.因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以一个能完成清理与释放内存工作的运算符delete。
注意new/delete不是库函数。
4.C++程序经常要调用C函数,而C程序只能用malloc/free管理动态内存。
5.new可以认为是malloc加构造函数的执行。
new出来的指针是直接带类型信息的。
而malloc返回的都是void*指针。
newdelete在实现上其实调用了malloc,free函数
6.new建立的对象你可以把它当成一个普通的对象,用成员函数访问,不要直接访问它的地址空间;malloc分配的是一块内存区域,就用指针访问好了,而且还可以在里面移动指针.
(12)声明内联函数的规则?
1)、含有递归调用的函数不能设置为inline;
2)、使用了复杂流程控制语句:
循环语句和switch语句,无法设置为inline;
3)、由于inline增加体积的特性,所以建议inline函数内的代码应很短小。
最好不超过5行。
4)、inline仅做为一种“请求”,特定的情况下,编译器将不理会inline关键字,而强制让函数成为普通函数。
出现这种情况,编译器会给出警告消息。
5)、在你调用一个内联函数之前,这个函数一定要在之前有声明或已定义为inline,如果在前面声明为普通函数,而在调用代码后面才定义为一个inline函数,程序可以通过编译,但该函数没有实现inline。
(13)面向对象的三大特性。
答:
封装、多态、继承
(14)宏与函数的区别。
答:
1.内联函数在运行时可调试,而宏定义不可以;
2.编译器会对内联函数的参数类型做安全检查或自动类型转换(同普通函数),而宏定义则不会;
3.内联函数可以访问类的成员变量,宏定义则不能;
4.在类中声明同时定义的成员函数,自动转化为内联函数。
(15)cstdio与stdio.h的区别
答:
在C语言中,stdio.h头文件是主要的。
而在后来的C++语言中,C只是C++的一个子集,且C++中,已不推荐再用C的类库,但为了对已有代码的保护,还是对原来的头文件支持。
cstdio是c++从C的stdio.h继承来的,在前面加C同时不要H后缀,在C++环境当然是选用前者,两者内容都一样,只是cstdio头文件中定义的名字被定义在命名空间std中。
使用后者就会带来额外的负担,需要区分哪些是
标准库明是C++特有的,哪些是继承过来的!
!
所以在C++中要尽量避免C风格的出现!
!
(16)extern的作用。
1)在C/C++中的应用,声明外部变量(全局变量)。
2)在C++文件中调用C方式编译的函数。
2、中等题
(17)一个栈的入栈顺序是A,B,C,D,E,则器出栈顺序不可能是?
()
A.EDCBA
B.DECBA
C.DCEAB
D.ABCDE
答:
C
C选项中AB次序出错,
如果想要AB这样输出,只能是A入栈立刻出栈,B入栈出栈。
A没有立刻出栈,则B一定会首先出栈。
(18)C++中不能被派生类继承的函数有?
答:
构造函数、析构函数
(19)看如下程序:
voidFUN(charstr[100]){
cout<}
输出什么结果?
答:
4
数组传参退化成指针
(20)介绍一下STL,简单说明STL如何实现vector。
答:
STL(标准模版库,StandardTemplateLibrary)它由容器算法迭代器组成。
STL有以下的一些优点:
1)可以方便容易地实现搜索数据或对数据排序等一系列的算法;
2)调试程序时更加安全和方便;
vector实质上就是一个动态数组,会根据数据的增加,动态的增加数组空间。
3、困难题
(21)C++在main()函数之前执行了什么?
答:
(注:
回答蓝色部分即可)
全局对象的构造函数,malloc需要的必要资源堆栈的初始化等。
(22)const与#define比较有何优点?
答:
1)const常量有数据类型,而宏常量没有数据类型。
编译器可以对前者进行类型安全检查。
而对后者只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不到的错误。
2)有些集成化的调试工具可以对const常量进行调试,但是不能对宏常量进行调试。
(23)一个空类的大小为多少?
请举例说明为什么?
答:
不为0,大多数编译器确定为1
例如classA{};
定义A[4];如果为大小为0,则不能确定A[0]A[1]的位置。
(24)如何让一个程序在main函数退出后继续执行?
使用atexit()或者_onexit()注册一个函数。
(25)查找错误
voidtest1()
{
charstring[10];
char*str1="0123456789";
strcpy(string,str1);
}
答:
数组越界
(26)将“引用”作为函数返回值类型的格式、好处和需要遵守的规则?
答:
(1)不能返回局部变量的引用。
(2)不能返回函数内部new分配的内存的引用。
(3)可以返回类成员的引用,但最好是const。
(4)流操作符重载返回值申明为“引用”的作用,流操作符<<和>>。
(27)什么是多态?
它是怎么实现的?
答:
一个接口多种方法。
编译器为每个类的对象提供一个虚表指针,这个指针指向对象所属类的虚表。
在程序运行时,根据对象的类型去初始化vptr,从而让vptr正确的指向所属类的虚表,从而在调用虚函数时,就能够找到正确的函数。
对于虚函数调用来说,每一个对象内部都有一个虚表指针,该虚表指针被初始化为本类的虚表。
所以在程序中,不管你的对象类型如何转换,但该对象内部的虚表指针是固定的,所以呢,才能实现动态的对象函数调用。
(28)内存分配的方式
1)静态存储区,程序编译时就分配好了,在整个程序运行期间都存在,如全局变量、常量
2)栈上分配,函数内的局部变量的分配方式,但分配的内存容易有限制
3)堆分配,如new,malloc分配的内存,需要手动释放
(29)strcpy()和memecpy()区别是什么?
答:
strcpy()和memcpy()都能用来拷贝某一块内存中的内容。
但strcpy传入参数为char*并且以’\0’结束
memcpy()传入参数为void*需要指定拷贝的长度。