C++面试题3

第3课 - 外企笔试题精选一

  1. 下面的代码输出是什么?为什么?

#include<iostream>

#include<malloc.h>

using namespace std;

class A

{

private:

         static int c_count;

public:

         A()

         {

                   c_count++;

}

~A()

         {

                   c_count--;

}

         static void Count()

         {

                   cout<<c_count<<endl;

}

};

Int A::c_count = 0;

int main()

{

         A* a=static_cast<A*>(malloc(sizeof(A)));

         a->Count();

         delete a;

         a->Count();

         return 0;

}

运行结果:

0

-1

分析:

         本题考查静态成员的使用和构造函数的使用。在使用中构造函数没用被调用,malloc只会在内存中申请一段内存,不会对这段内存做任何解释,也就是a只是指向堆空间中的一段内存但是并没有指向堆空间的对象,构造函数没有被调用。理论上我们使用new()才是正确。delete a;会调用析构函数,使得最后结构是-1。但是由于a没有明确指向一段对象,a就是一个野指针,c++中的静态成员在使用的时候可以看成只是引用了类型而忽略了对象,a->count();等价为A::Count();即使a是野指针也不会耽误程序的使用。

         这里也强调在c++中,我们要尽可能的使用new,delete函数,少使用malloc,free函数。它们的区别在于new在堆空间申请内存时会主动调用构造函数,delete在堆空间释放内存时会主动调用析构函数。

  1. 下面的代码输出是什么?为什么?

class A

{

public:

         virtual void test(int i)

         {

         cout<<”A::test”<<i<<endl;

}

void test()

{

         cout<<”A::test”<<endl;

}

};

class B:public A

{

public:

         void test(double i)

         {

                   cout<<”B::test”<<i<<endl;

}

};

int main()

{

         A* a = new B();

         B* b = new B();

         a->test(5);

         a->test(5);

         return 0;

}

运行结果:

         A::test5

         B::test5

         多态发生在子类和基类之间,函数声明必须完全一样。重载必须发生在同一个作用域之间。本题中子类和基类之间的函数参数值一个是int一个是double,是不一样的,不能发生多态。不发生多态,就发生了隐藏和覆盖。

  1. 下面描述正确的是()
  2. 面向对象编程需要面向对象语言的支持,如Java和C++等。
  3. 封装,继承和多态是面向对象的基本特征。
  4. 继承是面向对象中代码复用的唯一方式
  5. 多态的工作方式与重载相同

选择:B

         面向对象是一种思想,是一种编程的方法学,与编程语言没有关系,Java和C++只是增加了对面向对象的支持,面向程序C语言同样可以支持面向对象编程;继承是面向对象中代码复用的方式之一,包括组合;多态发成在子类与父类之间,重载发生在同一个作用域之间。

  1. 下面的代码输出是什么?为什么?

class A

{

private:

         int i;

public:

         virtual void test()

         {

                   cout<<”A::test”<<endl;

}

};

class B:public A

{

private:

         int i;

public:

         void test()

         {

                   cout<<”B::test”<<endl;

}

};

void f(A* p, int len)

{

         for(int i = 0;i<len;i++)

         {

                   p[i].test();

}

}

int main()

{

         B b[3];

         f(b,3);

         return 0;

}

运行;B::test之后卡死,段错误。

分析:

         t[i]是等价于*(t+i)的,指针运算就是地址的运算,是在编译的时候进行地址寻找的,t+i等价于 (unsigned int)t + i*sizeof(Type)。B是继承A的,也就是说sizeof(B)肯定是大于sizeof(A)的。p[i].test()等价于(p+i).test(),void f(A* p, int len)是按A的格式进行输入的,只有第一个位置是合理的,指针在移动的过程中无法指引B的整数位置,发生段错误。

         在数组上不要使用多态的使用,数组就是指针,也就是指针和多态不要一起使用。

  1. 下面描述正确的是()
  2. 一个应用程序启动后成为一个进程
  3. 进程是操作系统分配资源的基本单位
  4. 一个进程中可以创建多个线程,每个线程都共享进程的资源
  5. 操作系统可以在创建进程的时候不创建任何一个线程

答案选:ABC,每一个进程至少包含一个线程,线程就是我们C语言中的main()函数,main()函数在运行的过程中可以调用其他的线程。

  1. 下面程序的输出是什么?为什么?

class A

{

private:

         static int i;

public:

         A()

         {

         i++;

}

A(const A&)

         {

         i++;

}

static void output()

{

         cout<<i<<endl;

}

};

A f(A& a)

{

         A aa = a;

         return a;

}

int A::I = 0;

int main()

{

         A a;

         f(a).output();

         return 0;

}

运行结果:3

分析:

静态成员在使用的时候可以看成只是引用了类型而忽略了对象。A a;调用一次构造函数,f(a)将a地址传入,在函数内部A aa = a;调用第二次构造函数,return a;将a赋值给返回值对象,也就是临时对象,第三次使用构造函数。

         这里涉及在C语言中,函数是如何调用的。

  1. 下面程序输出是什么?为什么?

#include<iostream>

using namespace std;

#define FUNC(a,b) a = a+b;

                                     b = a-b;

                                     a = a-b

int main()

{

         int a = 3;

         int b = 4;

         if(a>b) FUNC(a,b);

         cout<<a<<” ”<<bendl;

}

运行结果:4  -1

分析:宏是直接的文本替换,没有括号,执行b = a-b; a = a-b,a=4, b=-1;

为了及时改错,可以改成:

#define FUNC(a,b) do{

a = a+b;

b = a-b;

a = a-b;

while(0)

  1. Telnet协议是基于下面哪种协议开发而来的()
  2. TCP
  3. UDP
  4. TCP and UDP
  5. none of above

答案选:A

  1. Please choose the correct options for the ISR below:()

interrupt double service(double p)

{

         Return p*p;

}

  1. ISR function should not return any value, service() cannot be used as a ISR.
  2. ISR function should not accept any parameter, service() annot be used as a ISR.
  3. service() is a valid ISR
  4. none of above

答案选:AB

中断服务程序不能有返回值;中断服务程序不能有参数;中断服务程序中不能有浮点运算;中断服务程序里面不能有printf函数。

  1. 有一组整型数,其中除了2个数字以外的其他数字都是两两成对出现的,编写程序找出这2个不成对出现的数字。

函数原型: 

void search_diff(int array[],int len,int* pa,int* pb);

示例:

void search_diff(int array[],int len,int* pa,int* pb);

int a = 0;

int b = 0;

int array[]={3,4,5,5,3,4,1,6,6,7,2,8,7,8};

search_diff(array,sizeof(a)/sizeof(*a),&a,&b);//调用后a,b为1,2或者a,b为2,1

#include <iostream>

#include <malloc.h>

using namespace std;

int first_one_bit(unsigned int v)

{

    int ret = 0;

   

    while( (v != 0) && ((v & 1) == 0) )

    {

        v = v >> 1;

        ret++;

    }

   

    return ret;

}

void search_diff(int array[], int len, int* pa, int* pb)

{

    if( (array != NULL) && (pa != NULL) && (pb != NULL) )

    {

        int r = 0;

        int flag = 0;

       

        for(int i=0; i<len; i++)

        {

            r = r ^ array[i];

        }

       

        flag = 1 << first_one_bit(r);

       

        *pa = 0;

        *pb = 0;

       

        for(int i=0; i<len; i++)

        {

            if( array[i] & flag )

            {

                *pa = *pa ^ array[i];

            }

            else

            {

                *pb = *pb ^ array[i];

            }

        }

    }

}

int main()

{

         int a = 0;

         int b = 0;

         int array[] = {3, 4, 5, 5, 3, 4, 1, 6, 6, 7, 2, 8, 7, 8};

    search_diff(array, sizeof(array)/sizeof(*array), &a, &b);

        

         cout<<a<<" "<<b<<endl;

}

  1. 打印一个N*N的矩阵,从首坐标(0,0)开始顺时针依次增大。

示例:5*5矩阵,其中数字1的坐标为(0,0)

1 2 3 4 5

16 17 18 19 6

15 24 25 20 7

14 23 22 21 8

13 12 11 10 9

程序:#include <iostream>

#include <malloc.h>

using namespace std;

template <int N>

class SpinMatrix

{

private:

    int m_matrix[N][N];

   

    struct Offset

    {

        int dx;

        int dy;

    };

   

    bool valid(int x, int y);

public:

    SpinMatrix();

    void run();

    void println();

    int scale();

};

template <int N>

SpinMatrix<N>::SpinMatrix()

{

    for(int i=0; i<N; i++)

    {

        for(int j=0; j<N; j++)

        {

            m_matrix[i][j] = 0;

        }

    }

}

template <int N>

bool SpinMatrix<N>::valid(int x, int y)

{

    bool ret = true;

   

    ret = ret && ((0 <= x) && (x < N));

    ret = ret && ((0 <= y) && (y < N));

    ret = ret && (m_matrix[x][y] == 0);

   

    return ret;

}

template <int N>

void SpinMatrix<N>::run()

{

    const Offset OFFSET[] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};

    const int OSLEN = sizeof(OFFSET) / sizeof(*OFFSET);

    int cx = 0;

    int cy = 0;

    int cd = 0;

    int i = 1;

   

    do

    {

        m_matrix[cx][cy] = i;

       

        if( !valid(cx + OFFSET[cd].dx, cy + OFFSET[cd].dy) )

        {

            cd = (cd + 1) % OSLEN;

        }

       

        cx += OFFSET[cd].dx;

        cy += OFFSET[cd].dy;

       

        i++;

    } while ( i <= N*N );

}

template <int N>

void SpinMatrix<N>::println()

{

    for(int i=0; i<N; i++)

    {

        for(int j=0; j<N; j++)

        {

            cout<<m_matrix[i][j]<<' ';

        }

       

        cout<<endl;

    }

   

    cout<<endl;

}

template <int N>

int SpinMatrix<N>::scale()

{

    return N;

}

int main()

{

    SpinMatrix<3> sm1;

    SpinMatrix<4> sm2;

   

    cout<<"3 * 3: "<<endl;

   

    sm1.run();

    sm1.println();

   

    cout<<"4 * 4: "<<endl;

   

    sm2.run();

    sm2.println();

}

原文地址:https://www.cnblogs.com/free-1122/p/11341956.html