欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C++常见面试题总结(1)

程序员文章站 2022-05-30 21:11:42
...

一、接口和抽象类的区别:
1。接口只给出方法声明,而不实现。抽象类中可以有方法的实现。
2。接口中不能包含常量、字段(域)、构造函数、析构函数、静态成员。抽象类可以。
3。接口可以多继承,抽象类不行。
4。接口中的所有成员默认为public,因此接口中不能有private修饰符。抽象类可以有私有成员数据


相同点:
(1) 都可以被继承
(2) 都不能被实例化
(3) 都可以包含方法声明
(4) 派生类必须实现未实现的方法
二、static和const的特点:
1。static:static修饰的变量在静态区。
1) 修饰局部变量时,若未初始化,默认值为0。当定义它的函数或者语句块结束的时候,作用域随之结束
2)修饰全局变量时,若未初始化,默认值为0。作用域在定义处到文件结尾。其他文件不能访问。这样其他文件中可以使用相同名字的变量,不会发生冲突。
3)修饰类内成员变量时,使其成为类的全局变量,会被类的所有对象共享,包括派生类的对象。因此,static成员必须在类外进行初始化,而不能在构造函数内进行初始化,不过也可以用const修饰static数据成员在类内初始化 。(也就是说static和const可以同时修饰一个变量)
4)修饰类内成员函数时,函数不含this指针。
可以独立访问,无须创建任何对象实例就可以访问。
当static成员函数在类外定义时不需要加static修饰符。
在静态成员函数的实现中不能直接引用类中的非静态成员,可以引用类中的静态成员。(不能同时使用const和static修饰成员函数。因为const修饰的函数不能修改类的实例,在函数中添加一个const this*指针 ,static修饰的函数没有this指针。
2。const:
1)const修饰变量使其变成常量。
2)修饰成员函数使其不能修改任何数据成员。函数内部不能调用非const函数。可以访问数据成员。
3)修饰对象时,不能访问非const函数,不能修改数据成员(public)但是可以访问。
const可以使程序增强健壮性。

const在 * 前,地址不可变,const在 * 后,值不可变


define和const的区别:
参考自:
(http://blog.csdn.net/love_gaohz/article/details/7567856)
(1) 编译器处理方式不同
  define宏是在预处理阶段展开。
  const常量是编译运行阶段使用。
(2) 类型和安全检查不同
  define宏没有类型,不做任何类型检查,仅仅是展开。
  const常量有具体的类型,在编译阶段会执行类型检查。
(3) 存储方式不同
  define宏仅仅是展开,有多少地方使用,就展开多少次,不会分配内存。(宏定义不分配内存,变量定义分配内存。)
  const常量会在内存中分配(可以是堆中也可以是栈中)。
  (4)const 可以节省空间,避免不必要的内存分配。 例如:
#define PI 3.14159 //常量宏
const doulbe Pi=3.14159; //此时并未将Pi放入ROM中 ……
double i=Pi; //此时为Pi分配内存,以后不再分配!
double I=PI; //编译期间进行宏替换,分配内存
double j=Pi; //没有内存分配
double J=PI; //再进行宏替换,又一次分配内存!
const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define一样给出的是立即数,所以,const定义的常量在程序运行过程中只有一份拷贝(因为是全局的只读变量,存在静态区),而 #define定义的常量在内存中有若干个拷贝。
(5) 提高了效率。 编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。
(6) 宏替换只作替换,不做计算,不做表达式求解;
宏预编译时就替换了,程序运行时,并不分配内存。
三、struct、union、class:
1, struct和union默认权限是public,class是private。
2、struct和class中的数据成员内存相互独立。Union的存储空间至少要容纳最大的数据成员。当给union中的一个数据成员赋值之后,其他数据成员的值也改变了。
3、Union不能含有引用类型的成员,不能作为基类,也不能有派生类,所以不能有虚函数。
4、struct默认继承方式为Public,class默认为private。
5、struct和union不能使用模版定义变量。class可以。
四:引用、指针的区别:
1。引用是变量的别名,不占用内存。指针是一个变量,指向变量的地址,占用内存。
2。引用创建时必须初始化,指针不用(但是注意,没有初始化的指针是不能用的。)
3、一旦引用初始化后,就不能改变引用所指向的变量; 指针可以改变指向别的对象
4、指针可以有多级,但是引用只能是一级
5。指针自增和引用的表示意义不一样。
6.不能建立数组的引用,但是可以有数组的指针。
7、不能返回局部变量的引用。不能返回函数内部new分配的内存的引用。
四、指针和数组的区别:
1。指针可以在任何区域创建,数组只能在*区(栈)或者静态区(全局变量)
2。作为函数参数时,数组退化为指针。
3。sizeof()得到的结果可能不同。
五: int (*s[10])(int) 表示的是什么?
int (*s[10])(int) 函数指针数组,每个指针指向一个int func(int param)的函数。
六:重载、覆盖、隐藏:
1。重载(overload):同类同函数名不同参
2。覆盖(override):覆盖有时也被叫做重写?不同类(父类和子类)同函数名同参
3。隐藏:不同类同名同参(父类没有virtual),隐藏父类函数。
不同类同名不同参,隐藏父类函数

class Base{
public:
virtual void fun();};

class A{
public:
/*隐藏父类的fun(),同名不同参,此时有两个名为fun函数,一个是继承自Base的fun(),一个是类A的fun(int a)*/
void fun(int a)

}

class B:public  A
{
void fun(int a)//隐藏类A的fun(int a),同名同参父类无virtual
}

七、多继承与多重继承
多继承:一个子类继承多个父类
多重继承:类A派生B,类B派生类C,这就称为多重继承。
虚继承是为了防止多重继承过程中产生数据冗余。
类中有虚函数表,通过指针调用虚函数。派生类会生成一个兼容基类的虚函数表。对象有虚函数指针(没有虚函数表)

八、深拷贝和浅拷贝:

浅拷贝:只进行简单的值拷贝。如果类内有指针类型的数据成员,在调用拷贝构造函数的时候,他们指向的是同一块内存。这就会出现问题。在调用析构函数的时候,会对同一块内存释放两次。
深拷贝:调用拷贝构造函数的时候,指针类型的数据成员指向不同的内存地址,在写拷贝构造函数的时候,指针要重新申请一块内存来拷贝数据。
例如:

class A
{public:
     A()
     {m_iAt=5;
     m_pA=new int[m_iA]
     }
     A(const A&a)
     {m_iA=a.m_ia;
     m_pA=new int[m_iA];
     for(int i=0;i<m_iA;i++)
     {m_pA[i]=a.m_pA[i];}

     }
private:
int m_iA;
int *m_pA;
     }

八:sizeof和strlen:
sizeof是指的存储能力。例如,char s[10]=“hello”,sizeof(s) =10。
strlen指的是当前存储了多少。对于数组s。strlen(s)=5.
sizeof是运算符,可以用类型做参数。具体而言,当参数分别如下时,sizeof返回的值表示的含义如下:
数组——编译时分配的数组空间大小;
指针——存储该指针所用的空间大小(存储该指针的地址的长度,是长整型,应该为4);
类型——该类型所占的空间大小;
对象——对象的实际占用空间大小;
函数——函数的返回类型所占的空间大小。函数的返回类型不能是void。
strlen是函数,参数只能是char *。


同时还应注意区分vector容器的size()和capacity()的区别。


九:inline内联函数:
inline关键字必须和函数体定义放在一起才可以实现内联,仅仅将inline放在函数声明之前不起任何作用。inline是一个用于实现的关键字而不是一个用于声明的关键字。对于类方法,定义在类体内部的方法自动成为内联方法。
内联函数是通过代码膨胀来执行的,在内联函数调用处复制函数代码,这样省去了普通函数调用的时空开销,提高了程序执行效率,但是由于代码复制增加了内存开销,所以内联函数应当是小函数、执行耗时短的函数。
十:线程和进程:

定义方面:进程是程序在某个数据集合上的一次运行活动;线程是进程中的一个执行路径。
角色方面:在支持线程机制的系统中,进程是系统资源分配的单位,线程是系统调度的单位。
资源共享方面:进程之间不能共享资源,而线程共享所在进程的地址空间和其它资源。同时线程还有自己的栈和栈指针,程序计数器等寄存器。
独立性方面:进程有自己独立的地址空间,而线程没有,线程必须依赖于进程而存在。
十一:is-a和has-a
is-a:继承
has-a:类中的数据成员是另一个类的实例