面试点滴

95次阅读

共计 1977 个字符,预计需要花费 5 分钟才能阅读完成。

语言面试题
#include <iostream>

using namespace std;

class A
{
public:
A() : m_ival(0)
{
test();
}

virtual void func()
{
cout << m_ival << endl;
}

void test()
{
func();
}

public:
int m_ival;
};

class B : public A
{
public:
B()
{
test();
}

void func()
{
++ m_ival;
cout << m_ival << endl;
}
};

int main()
{
A* p = new B;

p->test();

delete p;

return 0;
}
问 1:分析下面的程序,给出运行结果
输出:
0
1
2
问 二:在子类与父类构造函数中都调用 test(), 那么编译器是怎么确定应该调用的哪个 func() 函数版本呢?
相关概念:

构造函数未结束前,虚函数表未初始化完成,因此不能发生多态
动态联编不等价于多态:动态联编:编译原理中的概念多 态:面向对象理论。C++ 编译器在实现面向对象的多态时,使用动态联编的概念

发生了什么?

在构造 A 部分时:

在构造 A 部分时,回去构造 A 部分的虚函数表。在执行 A 的构造函数的函数体时,虚函数表是【完整】的
在 A 的构造函数中调用 Func(), 发生动态联编,查找虚函数表得到具体函数地址
A 中的 Func 被调用

在构造 B 部分时:

在构造 B 部分时,【虚函数表被更新】
在 B 的构造函数中调用 Func(),发生动态联编,查找虚函数表得到具体函数地址
B 中的 Func 被调用

总结:

在构造函数中,调用虚函数不会发生多态,但虚函数是动态联编的
虚函数的调用,都是通过查找虚函数表完成的

问 三:上述的代码是否有其它问题?

问题 1,未判断内存是否申请成功

问题 2

A* p = new B; delete p;
A 类指针 p 指向 B 类对象,在 delete 时,析构函数不是虚函数,因此,编译器就只会根据 p 的类型调用 A 类的析构函数,B 类的析构函数不会被调用!!!

要点

面试官需要的不只是“正确答案”
面试官会想要知道应试者的解题思路
面试官会从题中间“随机抓取”细节进行追问
面试官会把问题进行扩展(如:从语言扩展到编译器)

算法面试题
HR 问:编写代码将一个链表反转打印
面试者:需要思考的问题

这具体是一个什么样的链表(单链表?双向链表?循环链表)
链表中节点的数据是否允许改变
时间复杂度有没有要求
。。。

struct Node
{
int v;
struct Node* next;
};
void reversse_display_list(struct Node* list)
{
if(list)
{
reversse_display_list(list->next);

printf(“%d “, list->v);
}
}
void reversse_display_list_stack(struct Node* list)
{
if(list)
{
LinkStack<int> stack;

while(list) // O(n)
{
stack.push(list->v);

list = list->next;
}

while(stack.size() > 0 ) // O(n)
{
printf(“%d “, stack.top());

stack.pop();
}

printf(“\n”);
}
}
struct Node* reverse_list(struct Node* list) // O(n)
{
if(list)
{
struct Node* guard = NULL;
struct Node* next = list->next;

while(next)
{
list->next = guard;
guard = list;
list = next;
next = list->next;
}

list->next = guard;
}

return list;
}
要点

面试不是笔试,面试考察的不只是技术
面试官需要全方位考察应试者(沟通,品质,态度)
面试中尽量与面试官交流,获取解题的有用信息
面试中尽量写出完整代码,而不是纸上谈兵的忽悠
。。。

发散性思维问题
不用加减乘除运算符做整数加法
面试者:需要思考的问题

面试官想考察什么?
加法的底层本质是什么?
是否可以绕开“+”操作符的使用
。。。

int add_1(int a, int b)
{
int ret = 0;

asm volatile
(
“movl %%eax, %%ecx\n”
“addl %%ebx, %%ecx\n”
: “=c”(ret)
: “a”(a), “b”(b)
);

return ret;
}

int add_2(int a, int b)
{
int part = 0;
int carry = 0;

do
{
part = a ^ b;
carry = (a & b) << 1;

a = part;
b = carry;
} while(b != 0);

return a;
}
要点

不同公司对人才的要求是不同的
一些公司会更看重应试者的可塑性
学习,分析,思考能力是工作中必备的(面试需要考察)
计算机系统底层原理的学习必不可少
。。。

正文完
 0