第3课 - 外企笔试题精选一
- 下面的代码输出是什么?为什么?
#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在堆空间释放内存时会主动调用析构函数。
- 下面的代码输出是什么?为什么?
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,是不一样的,不能发生多态。不发生多态,就发生了隐藏和覆盖。
- 下面描述正确的是()
- 面向对象编程需要面向对象语言的支持,如Java和C++等。
- 封装,继承和多态是面向对象的基本特征。
- 继承是面向对象中代码复用的唯一方式
- 多态的工作方式与重载相同
选择:B
面向对象是一种思想,是一种编程的方法学,与编程语言没有关系,Java和C++只是增加了对面向对象的支持,面向程序C语言同样可以支持面向对象编程;继承是面向对象中代码复用的方式之一,包括组合;多态发成在子类与父类之间,重载发生在同一个作用域之间。
- 下面的代码输出是什么?为什么?
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的整数位置,发生段错误。
在数组上不要使用多态的使用,数组就是指针,也就是指针和多态不要一起使用。
- 下面描述正确的是()
- 一个应用程序启动后成为一个进程
- 进程是操作系统分配资源的基本单位
- 一个进程中可以创建多个线程,每个线程都共享进程的资源
- 操作系统可以在创建进程的时候不创建任何一个线程
答案选:ABC,每一个进程至少包含一个线程,线程就是我们C语言中的main()函数,main()函数在运行的过程中可以调用其他的线程。
- 下面程序的输出是什么?为什么?
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语言中,函数是如何调用的。
- 下面程序输出是什么?为什么?
#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)
- Telnet协议是基于下面哪种协议开发而来的()
- TCP
- UDP
- TCP and UDP
- none of above
答案选:A
- Please choose the correct options for the ISR below:()
interrupt double service(double p)
{
Return p*p;
}
- ISR function should not return any value, service() cannot be used as a ISR.
- ISR function should not accept any parameter, service() annot be used as a ISR.
- service() is a valid ISR
- none of above
答案选:AB
中断服务程序不能有返回值;中断服务程序不能有参数;中断服务程序中不能有浮点运算;中断服务程序里面不能有printf函数。
- 有一组整型数,其中除了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;
}
- 打印一个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();
}