第一次面试体验

来源:互联网 发布:藏宝库源码 编辑:程序博客网 时间:2024/06/08 14:16

人生中第一次参加宣讲会,第一次参加笔试面试,仅以此文勉励自己。

面试收获:

1.项目的经验真的很重要,很重要,很重要!!!

2.HR除了关心你的专业技能,还是会了解你的个人性格。

3.除了工作,还有生活,兴趣爱好也很重要

4.面试回答问题的过程,逻辑一定要清楚,有条理

笔试收获:题都很简单,要好好准备复习下基础知识。

技术面试:项目 项目 还是项目!!!

  大胆说出你的想法 你的问题 

  实事求是 真诚沟通

笔试问题:

1.this指针的作用?

答:一个指向当前对象的指针/地址。

        在调用成员函数时,函数通过一个隐藏参数收到一个this指针,该指针指向通过它调用函数的对象。

int GetWidth() const     {return this -> itsWidth;}int GetWidth() const     {return itsWidth;}int GetWidth() const     {(*this ).itsWidth;}
1.this只能在成员函数中使用,全局和静态函数都不能使用this

2.this在成员函数的开始前构造的,在成员的结束后清除

3.this存放会因为编译器不同,而放置的位置不同,可能是栈,寄存器,全局变量。


2.static什么作用?

static是C++中常用的修饰符,它被用来控制变量的存贮方式可见性,且在C和C++中的作用不同。

一.C语言中的static关键字

在C语言中,static可以用来修饰局部变量,全局变量以及函数。在不同的情况下static的作用不尽相同。

(1)修饰局部变量

一般情况下,对于局部变量是存放在栈区的,并且局部变量的生命周期在该语句块执行结束时便结束了。但是如果用static进行修饰的话,该变量便存放在静态数据区,其生命周期一直持续到整个程序执行结束。但是在这里要注意的是,虽然用static对局部变量进行修饰过后,其生命周期以及存储空间发生了变化,但是其作用域并没有改变,其仍然是一个局部变量,作用域仅限于该语句块。

在用static修饰局部变量后,该变量只在初次运行时进行初始化工作,且只进行一次

如:

  1. #include<stdio.h>  
  2. void fun()  
  3. {   
  4. static int a=1; a++;   
  5. printf("%d\n",a);  
  6. }  
  7. int main(void)  
  8. {   
  9. fun();   
  10. fun();   
  11. return 0;  
  12. }  

程序执行结果为: 2  3

说明在第二次调用fun()函数时,a的值为2,并且没有进行初始化赋值,直接进行自增运算,所以得到的结果为3.

对于静态局部变量如果没有进行初始化的话,对于整形变量系统会自动对其赋值为0,对于字符数组,会自动赋值为'\0'.

(2)修饰全局变量

对于一个全局变量,它既可以在本源文件中被访问到,也可以在同一个工程的其它源文件中被访问(只需用extern进行声明即可)。

如:

  1. //有file1.c  
  2. int a=1;  
  3. file2.c  
  4. #include<stdio.h>  
  5. extern int a;  
  6. int main(void)  
  7. {  
  8. printf("%d\",a);  
  9. return 0;  

则执行结果为 1

但是如果在file1.c中把int a=1改为static int a=1;

那么在file2.c是无法访问到变量a的。原因在于用static对全局变量进行修饰改变了其作用域的范围,由原来的整个工程可见变为本源文件可见。

(3)修饰函数

用static修饰函数的话,情况与修饰全局变量大同小异,就是改变了函数的作用域

二.C++中的static

在C++中static还具有其它功能

如果在C++中对类中的某个函数用static进行修饰,则表示该函数属于一个类而不是属于此类的任何特定对象

如果对类中的某个变量进行static修饰,表示该变量为类以及其所有的对象所有。

它们在存储空间中都只存在一个副本。可以通过类和对象去调用。

三.extern关键字

在C语言中,修饰符extern用在变量或者函数的声明前,用来说明“此变量/函数是在别处定义的,要在此处引用”。
在上面的例子中可以看出,在file2中如果想调用file1中的变量a,只须用extern进行声明即可调用a,这就是extern的作用。在这里要注意extern声明的位置对其作用域也有关系,如果是在main函数中进行声明的,则只能在main函数中调用,在其它函数中不能调用。其实要调用其它文件中的函数和变量,只需把该文件用#include包含进来即可,为啥要用extern?因为用extern会加速程序的编译过程,这样能节省时间。

在C++中extern还有另外一种作用,用于指示C或者C++函数的调用规范。比如在C++中调用C库函数,就需要在C++程序中用extern “C”声明要引用的函数。这是给链接器用的,告诉链接器在链接的时候用C函数规范来链接。主要原因是C++和C程序编译完成后在目标代码中命名规则不同,用此来解决名字匹配的问题。


3.private public protected什么作用?(引用http://www.jb51.net/article/54224.htm)

1.类的一个特征就是封装,public和private作用就是实现这一目的。所以:

用户代码(类外)可以访问public成员而不能访问private成员;private成员只能由类成员(类内)和友元访问。

2.类的另一个特征就是继承,protected的作用就是实现这一目的。所以:

protected成员可以被派生类对象访问,不能被用户代码(类外)访问。

现来看看如下示例:

#include<iostream>#include<assert.h>using namespace std;class A{public:  int a;  A(){    a1 = 1;    a2 = 2;    a3 = 3;    a = 4;  }  void fun(){    cout << a << endl;    //正确    cout << a1 << endl;   //正确    cout << a2 << endl;   //正确,类内访问    cout << a3 << endl;   //正确,类内访问  }public:  int a1;protected:  int a2;private:  int a3;};int main(){  A itema;  itema.a = 10;    //正确  itema.a1 = 20;    //正确  itema.a2 = 30;    //错误,类外不能访问protected成员  itema.a3 = 40;    //错误,类外不能访问private成员  system("pause");  return 0;}

继承中的特点:

先记住:不管是否继承,上面的规则永远适用!

有public, protected, private三种继承方式,它们相应地改变了基类成员的访问属性。

1.public继承:基类public成员,protected成员,private成员的访问属性在派生类中分别变成:public, protected, private

2.protected继承:基类public成员,protected成员,private成员的访问属性在派生类中分别变成:protected, protected, private

3.private继承:基类public成员,protected成员,private成员的访问属性在派生类中分别变成:private, private, private

但无论哪种继承方式,上面两点都没有改变:

1.private成员只能被本类成员(类内)和友元访问,不能被派生类访问

2.protected成员可以被派生类访问

再来看看以下代码:

1.public继承

代码如下:

#include<iostream>#include<assert.h>using namespace std;class A{public:  int a;  A(){    a1 = 1;    a2 = 2;    a3 = 3;    a = 4;  }  void fun(){    cout << a << endl;    //正确    cout << a1 << endl;   //正确    cout << a2 << endl;   //正确    cout << a3 << endl;   //正确  }public:  int a1;protected:  int a2;private:  int a3;};class B : public A{public:  int a;  B(int i){    A();    a = i;  }  void fun(){    cout << a << endl;       //正确,public成员    cout << a1 << endl;       //正确,基类的public成员,在派生类中仍是public成员。    cout << a2 << endl;       //正确,基类的protected成员,在派生类中仍是protected可以被派生类访问。    cout << a3 << endl;       //错误,基类的private成员不能被派生类访问。  }};int main(){  B b(10);  cout << b.a << endl;  cout << b.a1 << endl;   //正确  cout << b.a2 << endl;   //错误,类外不能访问protected成员  cout << b.a3 << endl;   //错误,类外不能访问private成员  system("pause");  return 0;}

2.protected继承:

代码如下:

#include<iostream>#include<assert.h>using namespace std;class A{public:  int a;  A(){    a1 = 1;    a2 = 2;    a3 = 3;    a = 4;  }  void fun(){    cout << a << endl;    //正确    cout << a1 << endl;   //正确    cout << a2 << endl;   //正确    cout << a3 << endl;   //正确  }public:  int a1;protected:  int a2;private:  int a3;};class B : protected A{public:  int a;  B(int i){    A();    a = i;  }  void fun(){    cout << a << endl;       //正确,public成员。    cout << a1 << endl;       //正确,基类的public成员,在派生类中变成了protected,可以被派生类访问。    cout << a2 << endl;       //正确,基类的protected成员,在派生类中还是protected,可以被派生类访问。    cout << a3 << endl;       //错误,基类的private成员不能被派生类访问。  }};int main(){  B b(10);  cout << b.a << endl;       //正确。public成员  cout << b.a1 << endl;      //错误,protected成员不能在类外访问。  cout << b.a2 << endl;      //错误,protected成员不能在类外访问。  cout << b.a3 << endl;      //错误,private成员不能在类外访问。  system("pause");  return 0;}

3.private继承:

代码如下:

#include<iostream>#include<assert.h>using namespace std;class A{public:  int a;  A(){    a1 = 1;    a2 = 2;    a3 = 3;    a = 4;  }  void fun(){    cout << a << endl;    //正确    cout << a1 << endl;   //正确    cout << a2 << endl;   //正确    cout << a3 << endl;   //正确  }public:  int a1;protected:  int a2;private:  int a3;};class B : private A{public:  int a;  B(int i){    A();    a = i;  }  void fun(){    cout << a << endl;       //正确,public成员。    cout << a1 << endl;       //正确,基类public成员,在派生类中变成了private,可以被派生类访问。    cout << a2 << endl;       //正确,基类的protected成员,在派生类中变成了private,可以被派生类访问。    cout << a3 << endl;       //错误,基类的private成员不能被派生类访问。  }};int main(){  B b(10);  cout << b.a << endl;       //正确。public成员  cout << b.a1 << endl;      //错误,private成员不能在类外访问。  cout << b.a2 << endl;      //错误, private成员不能在类外访问。  cout << b.a3 << endl;      //错误,private成员不能在类外访问。  system("pause");  return 0;}

通过以上的代码都备有较为详尽的注释,读者应该能够理解。仔细看代码中派生类B中定义了和基类同名的成员a,此时基类的a仍然存在,可以验证。

int main(){  cout << sizeof(A) << endl;  cout << sizeof(B) << endl;  system("pause");  return 0;}

输出:

16

20

所以派生类包含了基类所有成员以及新增的成员,同名的成员被隐藏起来,调用的时候只会调用派生类中的成员。

如果要调用基类的同名成员,可以用以下方法:

int main(){  B b(10);  cout << b.a << endl;  cout << b.A::a << endl;  system("pause");  return 0;}

输出:

10

4

记得这里是在类外访问,而a在基类中是public,所以继承方式应该为public,使得a在派生类中仍然为public,在类外可以访问。


4.纯虚函数什么作用?(引用自http://blog.csdn.net/xwpc702/article/details/8670025)

虚函数为了重载和多态的需要,在基类中是有定义的,即便定义是空,所以子类中可以重写也可以不写基类中的此函数!
纯虚函数在基类中是没有定义的,必须在子类中加以实现,很像java中的接口函数!
虚函数
引入原因:为了方便使用多态特性,我们常常需要在基类中定义虚函数。
class Cman
{
public:
virtual void Eat(){……};
void Move();
private:
};
class CChild : public CMan
{
public:
virtual void Eat(){……};
private:
};
CMan m_man;
CChild m_child;
CMan *p ;//这才是使用的精髓,如果不定义基类的指针去使用,没有太大的意义
p = &m_man ;
p->Eat(); //始终调用CMan的Eat成员函数,不会调用 CChild 的
p = &m_child;
p->Eat(); //如果子类实现(覆盖)了该方法,则始终调用CChild的Eat函数
//不会调用CMan 的 Eat 方法;如果子类没有实现该函数,则调用CMan的Eat函数
p->Move(); //子类中没有该成员函数,所以调用的是基类中的
纯虚函数
引入原因:
1、同“虚函数”;
2、在很多情况下,基类本身生成对象是不合情理的。例如,动物作为一个基类可以派生出老虎、孔雀等子类,但动物本身生成对象明显不合常理。
纯虚函数就是基类只定义了函数体,没有实现过程,定义方法如: virtual void Eat() = 0; 不要 在cpp中定义;

纯虚函数相当于接口,不能直接实例话,需要派生类来实现函数定义;
有的人可能在想,定义这些有什么用啊 ,我觉得很有用,比如你想描述一些事物的属性给别人,而自己不想去实现,就可以定义为纯虚函数。说的再透彻一些。比如盖楼房,你是老板,你给建筑公司描述清楚你的楼房的特性,多少层,楼顶要有个花园什么的,建筑公司就可以按照你的方法去实现了,如果你不说清楚这些,可能建筑公司不太了解你需要楼房的特性。用纯需函数就可以很好的分工合作了

虚函数和纯虚函数区别
观点一:
类里声明为虚函数的话,这个函数是实现的,哪怕是空实现,它的作用就是为了能让这个函数在它的子类里面可以被重载,这样的话,这样编译器就可以使用后期绑定来达到多态了
纯虚函数只是一个接口,是个函数的声明而已,它要留到子类里去实现。
class A{
protected:
void foo();//普通类函数
virtual void foo1();//虚函数
virtual void foo2() = 0;//纯虚函数
}
观点二:
虚函数在子类里面也可以不重载的;

但纯虚必须在子类去实现,这就像Java的接口一样。通常我们把很多函数加上virtual,是一个好的习惯,虽然牺牲了一些性能,但是增加了面向对象的多态性,因为你很难预料到父类里面的这个函数不在子类里面不去修改它的实现
观点三:
虚函数的类用于“实作继承”,继承接口的同时也继承了父类的实现。当然我们也可以完成自己的实现。

纯虚函数的类用于“介面继承”,主要用于通信协议方面。关注的是接口的统一性,实现由子类完成。一般来说,介面类中只有纯虚函数的。
观点四:
带纯虚函数的类叫虚基类,这种基类不能直接生成对象,而只有被继承,并重写其虚函数后,才能使用。这样的类也叫抽象类。
虚函数是为了继承接口和默认行为
纯虚函数只是继承接口,行为必须重新定义


个人总结:

不要虚度每一个今天,小伙!你与职场的要求还差的很远!但是你的面试表现还是很棒的,继续加油!!!