IT面试

1.三个float:a,b,c。 问值 (a+b)+c==(b+a)+c   (a+b)+c==(a+c)+b
两者都不行。在比较float或double时,不能简单地比较。由于计算误差,相等的概率很低。应判断两数之差是否落在区间(-e,e)内。这个e应比浮点数的精度大一个数量级。
2.请讲一讲析构函数和虚函数的用法和作用?
析构函数是特殊的类成员函数,它没有返回类型,没有参数,不能随意调用,也没有重载,只有在类对象的生命期结束的时候,由系统自动调用。 有适放内存空间的做用。
虚函数是C++多态的一种表现, 使用虚函数,我们可以灵活的进行动态绑定,当然是以一定的开销为代价。
3.全局变量和局部变量有什么区别?实怎么实现的?操作系统和编译器是怎么知道的?
生命周期不同:全局变量随主程序创建和创建,随主程序销毁而销毁。

              局部变量在局部函数内部,甚至局部循环体等内部存在,退出就不存在;内存中分配在全局数据区。
使用方式不同:通过声明后全局变量程序的各个部分都可以用到。   
              局部变量只能在局部使用;分配在栈区。
操作系统和编译器通过内存分配的位置来知道的,全局变量分配在全局数据段并且在程序开始运行的时候被加载。局部变量则分配在堆栈里面。
4.多态。overload 和 override的区别。
overload是重载,重载是一种参数多态机制,即代码通过参数的类型或个数不同而实现的多态机制。 是一种静态的绑定机制(在编译时已经知道具体执行的是哪个代码段)。  
 override是覆盖。覆盖是一种动态绑定的多态机制。即在父类和子类中同名元素(如成员函数)有不同的实现代码。执行的是哪个代码是根据运行时实际情况而定的。

重载Overload特点
public bool withdraw(double amt, string name)
public double withdraw(double amt)
1、方法名必须相同2、参数列表必须不相同3、返回值类型可以不相同
注意:override存在于继继承的关系类中。
覆写Override特点(三相同):
public override bool withdraw(...)
1、方法名相同2、参数列表相同3、返回值类型相同
注意:存在于同一类中,但是只有虚方法和抽象方法才能被覆写.
5.解释堆和栈的区别。
在传统的C中堆和栈实际是一块物理内存,堆主要用来动态分配内存,从堆栈内存的低端向上分配;而栈主要用来传递函数参数、返回值和局部参数内存分配,是从堆栈内存的高端向下分配,俗称压栈和出栈;堆是动态分配,比如用new,malloc分配,需要手工释放,不然会导致memory leak,栈是静态分配,比如函数调用是需要分配堆栈,但堆栈能自动释放.
6.论述含参数的宏与函数的优缺点。
宏是编译期的,函数是运行期的;宏不是实体,而函数是一个可寻址的实体;宏只是编译期替换,在程序里每遇到S(a,b),就用a*b代替,a和b两个实体并没有由宏实际产生,而函数S会在栈中定义两个对象a和b。宏没有生存期、作用域之类的概念,而函数就有。
7.非C++内建型别 A 和 B,在哪几种情况下B能隐式转化为A?
答:
a. class B : public A { ……} // B公有继承自A,可以是间接继承的
b. class B { operator A( ); } // B实现了隐式转化为A的转化
c. class A { A( const B& ); } // A实现了non-explicit的参数为B(可以有其他带默认值的参数)构造函数
d. A& operator= ( const A& ); // 赋值操作,虽不是正宗的隐式类型转换,但也可以勉强算一个
8.C++中的空类,默认产生哪些类成员函数?
答:
class Empty
{
public:
    Empty();                          // 缺省构造函数
    Empty( const Empty& );            // 拷贝构造函数
    ~Empty();                         // 析构函数
    Empty& operator=( const Empty& ); // 赋值运算符
    Empty* operator&();               // 取址运算符
    const Empty* operator&() const;   // 取址运算符 const
};
9.头文件的作用是什么?
答:一、通过头文件来调用库功能。在很多场合,源代码不便(或不准)向用户公布,只要向用户提供头文件和二进制的库即可。用户只需要按照头文件中的接口声明来调用库功能,而不必关心接口怎么实现的。编译器会从库中提取相应的代码。
二、头文件能加强类型安全检查。如果某个接口被实现或被使用时,其方式与头文件中的声明不一致,编译器就会指出错误,这一简单的规则能大大减轻程序员调试、改错的负担。
10.内存的分配方式的分配方式有几种?
答:一、从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量。
二、在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
三、从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。

11.假设现有一个单向的链表,但是只知道只有一个指向该节点的指针p,并且假设这个节点不是尾节点,试编程实现删除此节点
参考:将下一个节点的内容复制到本节点上,然后删除下一个节点。

12.字符指针、浮点数指针、以及函数指针这三种类型的变量哪个占用的内存最大?为什么?
答案:指针变量也占用内存单元,而且所有指针变量占用内存单元的数量都是相同的。就是说,不管是指向何种对象的指针变量,它们占用内存的字节数都是一样的,并且要足够把程序中所能用到的最大地址表示出来(通常是一个机器字长)。

13.类ClassB从ClassA派生,那么ClassA *a = new ClassB(…); 试问该表达是否合法?为什
么?
答案:派生类的指针指向基类的对象是错误的,不能通过编译的; 基类的指针可以指向派生类的对象,调用派生类的函数。

14.如果ClassA中定义并实现虚函数int func(void),ClassB中也实现该函数,那么上述变量

a->func()将调用哪个类里面的函数?如果int func(void)不是虚函数,情况又如何?为什么?
答案:第一问调用的是B的。第二问调用A的。
虚函数的一个典型应用,虚函数只能借助于指针或者引用来达到多态的效果
如果没有定义成虚函数:------
class A{
public:
void print(){ cout<<”This is A”<<endl;}
};

class B:public A{
public:
void print(){ cout<<”This is B”<<endl;}
};

int main(){   //为了在以后便于区分,我这段main()代码叫做main1
A a;  B b;
A* p1=&a;
A* p2=&b;
p1->print();
p2->print();
}
结果是两个This is A
如果定义成虚函数:---------
class A{
public:
virtual void print(){ cout<<”This is A”<<endl;}  //现在成了虚函数了
};

class B:public A{
public:
void print(){ cout<<”This is B”<<endl;}  //这里不需要在前面加上关键字virtual,只需在把基类的成员函数设为virtual,其派生类的相应的函数也会自动变为虚函数
};
再运行main输出的结果就是This is A和This is B。

15.char **p, a[16][8];  问:p=a是否会导致程序在以后出现问题?为什么?
参考: 这个不会导致出现问题,但是要注意p的使用,如a[1][2] 等价的为 *(*(p+1)+2)而不是*(p+11),
会的,这样会出现编译错误  正确的是:char a[5][5]; char (*p)[5]; p=a;

16.应用程序在运行时的内存包括代码区和数据区,其中数据区又包括哪些部分?
参考:对于一个进程的内存空间而言,可以在逻辑上分成3个部份:代码区,静态数据区和动态数据区。动态数据区一般就是“堆栈”。栈是一种线性结构,堆是一种链式结构。进程的每个线程都有私有的“栈”。全局变量和静态变量分配在静态数据区,本地变量分配在动态数据区,即堆栈中。程序通过堆栈的基地址和偏移量来访问本地变量。

17.用最有效率的方法算出2乘以8等於几?
移位

18.#include “filename.h”和#include <filename.h>的区别?
对于#include <filename.h>编译器从标准库开始搜索filename.h;对于#include “filename.h”编译器从用户工作路径开始搜索filename.h。

19.头文件的作用是什么?
一、通过头文件来调用库功能。在很多场合,源代码不便(或不准)向用户公布,只要向用户提供头文件和二进制的库即可。用户只需要按照头文件中的接口声明来调用库功能,而不必关心接口怎么实现的。编译器会从库中提取相应的代码。
二、头文件能加强类型安全检查。如果某个接口被实现或被使用时,其方式与头文件中的声明不一致,编译器就会指出错误,这一简单的规则能大大减轻程序员调试、改错的负担。

20.C++函数中值的传递方式有哪几种?
C++函数的三种传递方式为:值传递、指针传递和引用传递。

21.内存的分配方式的分配方式有几种?
答:一、从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量。
二、在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
三、从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。

22.C++里面是不是所有的动作都是main()引起的?如果不是,请举例.
比如全局变量的初始化,就不是由main函数引起的
举例: class A{};   
       a;   //a的构造函数限执行   
       int main() {}

23.多态类中的虚函数表是Compile-Time,还是Run-Time时建立的?

答案:虚拟函数表是在编译期就建立了,各个虚拟函数这时被组织成了一个虚拟函数的入口地址的数组.而对象的隐藏成员--虚拟函数表指针是在运行期--也就是构造函数被调用时进行初始化的,这是实现多态的关键.

24.一个父类写了一个virtual 函数,如果子类覆盖它的函数不加virtual ,也能实现多态?

在子类的空间里,有没有父类的这个函数,或者父类的私有变量? (华为笔试题

答案:只要基类在定义成员函数时已经声明了virtue关键字,在派生类实现的时候覆盖该函数时,virtue关键字可加可不加,不影响多态的实现。子类的空间里有父类的所有变量(static除外)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值