vc面试题目

class B
{
public:
    B()
    {
        cout << "default constructor" << endl;
    }
    ~B()
    {
        cout << "destructed" << endl;
    }
    B(int i) :data(i)
    {
        cout << "constructed by parameter" << data << endl;
    }
private:
    int data;
};
B Play(B b)
{
    return b;
}

int _tmain(int argc, _TCHAR* argv[])
{
//下列结果是什么
    B temp = Play(5);
    //Play(5);
    getchar();
    return 0;
}

第二题:

main 主函数执行完毕后,是否可能会再执行一段代码,给出说明?
答案:可以,可以用_onexit 注册一个函数,它会在main 之后执行
int fn1(void), fn2(void), fn3(void), fn4 (void);
void main( void )
{
String str("zhanglin");
_onexit( fn1 );
_onexit( fn2 );
_onexit( fn3 );
_onexit( fn4 );
printf( "This is executed first.\n" );
}
int fn1()
{
printf( "next.\n" );
return 0;
}
int fn2()
{
printf( "executed " );
return 0;
}
int fn3()
{
printf( "is " );
return 0;
}
int fn4()
{
printf( "This " );
return 0;
}


第三题
如何打印出当前源文件的文件名以及源文件的当前行号?
答案:
cout << __FILE__ ;
cout<<__LINE__ ;
__FILE__和__LINE__是系统预定义宏,这种宏并不是在某个文件中定义的,而是
由编译器定义的。


常见笔试/面试题目
2005 年 人在江湖 zhanglin@sjtu.edu.cn
1.已知strcpy 函数的原型是:
char *strcpy(char *strDest, const char *strSrc);
其中strDest 是目的字符串,strSrc 是源字符串。不调用C++/C 的字符串库函数,
请编写函数 strcpy
答案:
char *strcpy(char *strDest, const char *strSrc)
{
if ( strDest == NULL || strSrc == NULL)
return NULL ;
if ( strDest == strSrc)
return strDest ;
char *tempptr = strDest ;
while( (*strDest++ = *strSrc++) != ‘\0’)
;
return tempptr ;
}
2.已知类String 的原型为:
class String
{
public:
String(const char *str = NULL); // 普通构造函数
String(const String &other); // 拷贝构造函数
~ String(void); // 析构函数
String & operate =(const String &other); // 赋值函数
private:
char *m_data; // 用于保存字符串
};
请编写String 的上述4 个函数。
答案:
String::String(const char *str)
{
if ( str == NULL ) //strlen在参数为NULL时会抛异常才会有这步判断
{
m_data = new char[1] ;
m_data[0] = '\0' ;
}
else
{
m_data = new char[strlen(str) + 1];
strcpy(m_data,str);
}
}
String::String(const String &other)
{
m_data = new char[strlen(other.m_data) + 1];
strcpy(m_data,other.m_data);
}
String & String::operator =(const String &other)
{
if ( this == &other)
return *this ;
delete []m_data;
m_data = new char[strlen(other.m_data) + 1];
strcpy(m_data,other.m_data);
return *this ;
}
String::~ String(void)
{
delete []m_data ;
}
3.简答
3.1 头文件中的ifndef/define/endif 干什么用?
答:防止该头文件被重复引用。
3.2#include <filename.h> 和#include “filename.h” 有什么区别?
答:对于#include <filename.h> ,编译器从标准库路径开始搜索filename.h
对于#include “filename.h”,编译器从用户的工作路径开始搜索filename.h
3.3 在C++ 程序中调用被C 编译器编译后的函数,为什么要加extern “C”?
答:C++语言支持函数重载,C 语言不支持函数重载。函数被C++编译后在库
中的名字与C 语言的不同。假设某个函数的原型为: void foo(int x, int y);
该函数被C 编译器编译后在库中的名字为_foo , 而 C++ 编译器则会产生像
_foo_int_int 之类的名字。
C++提供了C 连接交换指定符号extern“C”来解决名字匹配问题。
3.4 一个类有基类、内部有一个其他类的成员对象,构造函数的执行顺序是怎样
的。(Autodesk)
答:先执行基类的(如果基类当中有虚基类,要先执行虚基类的,其他基类则
按照声明派生类时的顺序依次执行),再执行成员对象的,最后执行自己的。
3.5 请描述一个你熟悉的设计模式(Autodesk)
3.6 在UML 中,聚合(aggregation)和组合(composition)有什么区别 Autodesk)
答案:聚合关系更强,类似于pages 和book 的关系;组合关系要弱,类似于books
和bookshelf 的关系。
3.7C#和C++除了语法上的差别以外,有什么不同的地方?(Autodesk,Microsoft)
答案:(C#我只是了解,不是很精通)
(1)c#有垃圾自动回收机制,程序员不用担心对象的回收。(2)c#严禁使用指针,
只能处理对象。如果希望使用指针,则仅可在unsafe 程序块中能使用指针。(3)c#
只能单继承。(4)必须通过类名访问静态成员。不能像C++中那样,通过对象访
问静态成员。(5)在子类中覆盖父类的虚函数时必须用关键字override,覆盖父类
的方法要用关键字new
3.8ADO.net 和ADO 的区别?
答案:实际上除了“能够让应用程序处理存储于 DBMS 中的数据“这一基本相
似点外,两者没有太多共同之处。但是ADO 使用OLE DB 接口并基于微软的
COM 技术,而ADO.NET 拥有自己的ADO.NET 接口并且基于微软的.NET 体系
架构。众所周
知.NET 体系不同于
COM 体系,
ADO.NET 接口也
就完全不同于ADO
和OLE DB 接口,
这也就是说
ADO.NET 和ADO
是两种数据访问方
式。ADO.net 提供
对XML 的支持。
3.9 New delete 与malloc free 的区别 ( Autodesk)
答案:用malloc 函数不能初始化对象,new 会调用对象的构造函数。Delete 会
调用对象的destructor,而free 不会调用对象的destructor.
3.10 #define DOUBLE(x) x+x (Autodesk)
i = 5*DOUBLE(10); i 是多少?正确的声明是什么?
答案:i 为55。正确的声明是#define DOUBLE(x) (x+x)
3.11 有哪几种情况只能用intialization list 而不能用assignment? (Autodesk)
答案:当类中含有const、reference 成员变量;基类的构造函数都需要参数;类
中含有其他类的成员变量,而该类的构造函数都需要参数。
3.11 C++是不是类型安全的? (Autodesk)
答案:不是。两个不同类型的指针之间可以强制转换。C#是类型安全的。
3.12 main 函数执行以前,还会执行什么代码? (Autodesk)
答案:全局对象的构造函数会在main 函数之前执行。
3.13 描述内存分配方式以及它们的区别。 (Autodesk , Microsoft)
答案:1) 从静态存储区域分配。内存在程序编译的时候就已经分配好,这块
内存在程序的整个运行期间都存在。例如全局变量,static 变量。
(2) 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上
创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理
器的指令集。
(3) 从堆上分配,亦称动态内存分配。程序在运行的时候用malloc 或new 申
请任意多少的内存,程序员自己负责在何时用free 或delete 释放内存。动态内
存的生存期由我们决定,使用非常灵活,但问题也最多。
3.14 什么是虚拟存储器?virtual memory 怎样映射到physical memory?页面替换
算法有哪些? (Microsoft)
见操作系统 p238 页。掌握的页面替换算法NRU,FIFO,第二次机会页面替换
算法,LRU
3.15 有四个同样的容器,里面装满了粒数相同的药丸,正常药丸的质量为m,变
质药丸的质量为m+1,现在已知这四个容器中,有一个装的全是变质药丸,用电
子秤只称一次,找出哪个容器装的是变质药丸(Microsoft)
答案:把四个容器依次编号为1、2、3、4,然后从中分别取出1、2、3、4 粒药
丸,称这10 粒药丸的质量,如果质量为10m+1,则说明第一个容器装的是变质药
丸,如果为10m+2 则说明第二个装的变质药丸,依次类推。
3.16 比较一下C++中static_cast 和 dynamic_cast 的区别。 (Autodesk)
3.17 Struct 和class 的区别 (Autodesk)
答案:struct 中成员变量和成员函数默认访问权限是public,class 是private
3.18 当一个类A 中没有生命任何成员变量与成员函数,这时sizeof(A)的值是多
少,如果不是零,请解释一下编译器为什么没有让它为零。(Autodesk)
答案:肯定不是零。我举个反例,如果是零的话,声明一个class A[10]对象数组,
而每一个对象占用的空间是零,这时就没办法区分A[0],A[1]…了
3.19 在8086 汇编下,逻辑地址和物理地址是怎样转换的?(Intel)
答案:通用寄存器给出的地址,是段内偏移地址,相应段寄存器地址*10H+通用
寄存器内地址,就得到了真正要访问的地址。
3.20 描述一下C++的多态(microsoft)
答案:C++的多态表现在两个部分,一个是静态连编下的函数重载,运算符重载;
动态连编下的虚函数、纯虚函数(抽象类)
4.写出BOOL,int,float,指针类型的变量a 与零的比较语句。
答案:
BOOL : if ( !a )
int : if ( a == 0)
float : const EXPRESSION EXP = 0.000001
if ( a < EXP && a >-EXP)
pointer : if ( a != NULL)
5.请说出const 与#define 相比优点
答案:
(1) const 常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行
类型安全检查。而对后者只进行字符替换,没有类型安全检查,并且在字符替
换可能会产生意料不到的错误。
(2) 有些集成化的调试工具可以对 const 常量进行调试,但是不能对宏常量进
行调试。
6.简述数组与指针的区别
数组要么在静态存储区被创建(如全局数组),要么在栈上被创建。指针可以随
时指向任意类型的内存块。
(1)修改内容上的差别
char a[] = “hello”;
a[0] = ‘X’;
char *p = “world”; // 注意p 指向常量字符串
p[0] = ‘X’; // 编译器不能发现该错误,运行时错误
(2) 用运算符sizeof 可以计算出数组的容量(字节数)。sizeof(p),p 为指针得到的
是一个指针变量的字节数,而不是p 所指的内存容量。C++/C 语言没有办法知
道指针所指的内存容量,除非在申请内存时记住它。
注意当数组作为函数的参数进行传递时,该数组自动退化为同类型的指针。
char a[] = "hello world";
char *p = a;
cout<< sizeof(a) << endl; // 12 字节
cout<< sizeof(p) << endl; // 4 字节
计算数组和指针的内存容量
void Func(char a[100])
{
cout<< sizeof(a) << endl; // 4 字节而不是100 字节
}
7.类成员函数的重载、覆盖和隐藏区别
答案:
成员函数被重载的特征:
(1)相同的范围(在同一个类中);
(2)函数名字相同;
(3)参数不同;
(4)virtual 关键字可有可无。
覆盖是指派生类函数覆盖基类函数,特征是:
(1)不同的范围(分别位于派生类与基类);
(2)函数名字相同;
(3)参数相同;
(4)基类函数必须有virtual 关键字。
“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下:
(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual
关键字,基类的函数将被隐藏(注意别与重载混淆)。
(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没
有virtual 关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)
8.There are two int variables: a and b, don’t use “if”, “? :”, “switch”
or other judgement statements, find out the biggest one of the two
numbers.
答案:( ( a + b ) + abs( a – b ) ) / 2
9.如何打印出当前源文件的文件名以及源文件的当前行号?
答案:
cout << __FILE__ ;
cout<<__LINE__ ;
__FILE__和__LINE__是系统预定义宏,这种宏并不是在某个文件中定义的,而是
由编译器定义的。
10.main 主函数执行完毕后,是否可能会再执行一段代码,给出说明?
答案:可以,可以用_onexit 注册一个函数,它会在main 之后执行
int fn1(void), fn2(void), fn3(void), fn4 (void);
void main( void )
{
String str("zhanglin");
_onexit( fn1 );
_onexit( fn2 );
_onexit( fn3 );
_onexit( fn4 );
printf( "This is executed first.\n" );
}
int fn1()
{
printf( "next.\n" );
return 0;
}
int fn2()
{
printf( "executed " );
return 0;
}
int fn3()
{
printf( "is " );
return 0;
}
int fn4()
{
printf( "This " );
return 0;
}
The _onexit function is passed the address of a function (func) to be called when
the program terminates normally. Successive calls to _onexit create a register of
functions that are executed in LIFO (last-in-first-out) order. The functions passed
to _onexit cannot take parameters.
11.如何判断一段程序是由C 编译程序还是由C++编译程序编译的?
答案:
#ifdef __cplusplus
cout<<"c++";
#else
cout<<"c";
#endif
12.文件中有一组整数,要求排序后输出到另一个文件中
答案:
void Order(vector<int> &data) //起泡排序
{
int count = data.size() ;
int tag = false ;
for ( int i = 0 ; i < count ; i++)
{
for ( int j = 0 ; j < count - i - 1 ; j++)
{
if ( data[j] > data[j+1])
{
tag = true ;
int temp = data[j] ;
data[j] = data[j+1] ;
data[j+1] = temp ;
}
}
if ( !tag )
break ;
}
}
void main( void )
{
vector<int>data;
ifstream in("c:\\data.txt");
if ( !in)
{
cout<<"file error!";
exit(1);
}
int temp;
while (!in.eof())
{
in>>temp;
data.push_back(temp);
}
in.close();
Order(data);
ofstream out("c:\\result.txt");
if ( !out)
{
cout<<"file error!";
exit(1);
}
for ( i = 0 ; i < data.size() ; i++)
out<<data[i]<<" ";
out.close();
}
13.排序方法比较(intel)
排序方法 平均时间 最坏时间 辅助存储
直接插入排序
起泡排序
快速排序
简单选择排序
堆排序
归并排序
基数排序
14.一个链表的结点结构
struct Node
{
int data ;
Node *next ;
};
typedef struct Node Node ;
(1)已知链表的头结点head,写一个函数把这个链表逆序 ( Intel)
Node * ReverseList(Node *head) //链表逆序
{
if ( head == NULL || head->next == NULL )
return head;
Node *p1 = head ;
Node *p2 = p1->next ;
Node *p3 = p2->next ;
p1->next = NULL ;
while ( p3 != NULL )
{
p2->next = p1 ;
p1 = p2 ;
p2 = p3 ;
p3 = p3->next ;
}
p2->next = p1 ;
head = p2 ;
return head ;
}
(2)已知两个链表head1 和head2 各自有序,请把它们合并成一个链表
依然有序。
Node * Merge(Node *head1 , Node *head2)
{
if ( head1 == NULL)
return head2 ;
if ( head2 == NULL)
return head1 ;
Node *head = NULL ;
Node *p1 = NULL;
Node *p2 = NULL;
if ( head1->data < head2->data )
{
head = head1 ;
p1 = head1->next;
p2 = head2 ;
}
else
{
head = head2 ;
p2 = head2->next ;
p1 = head1 ;
}
Node *pcurrent = head ;
while ( p1 != NULL && p2 != NULL)
{
if ( p1->data <= p2->data )
{
pcurrent->next = p1 ;
pcurrent = p1 ;
p1 = p1->next ;
}
else
{
pcurrent->next = p2 ;
pcurrent = p2 ;
p2 = p2->next ;
}
}
if ( p1 != NULL )
pcurrent->next = p1 ;
if ( p2 != NULL )
pcurrent->next = p2 ;
return head ;
}
(2)已知两个链表head1 和head2 各自有序,请把它们合并成一个链表
依然有序,这次要求用递归方法进行。 ( Autodesk)
答案:
Node * MergeRecursive(Node *head1 , Node *head2)
{
if ( head1 == NULL )
return head2 ;
if ( head2 == NULL)
return head1 ;
Node *head = NULL ;
if ( head1->data < head2->data )
{
head = head1 ;
head->next = MergeRecursive(head1->next,head2);
}
else
{
head = head2 ;
head->next = MergeRecursive(head1,head2->next);
}
return head ;
}
15.分析一下这段程序的输出 (Autodesk)
class B
{
public:
B()
{
cout<<"default constructor"<<endl;
}
~B()
{
cout<<"destructed"<<endl;
}
B(int i):data(i)
{
cout<<"constructed by parameter" << data <<endl;
}
private:
int data;
};
B Play( B b)
{
return b ;
}
int main(int argc, char* argv[])
{
B temp = Play(5);
return 0;
}
出题人耍了个小花招够恶心,请大家执行一下看看。
16.写一个函数找出一个整数数组中,第二大的数(microsoft)
答案:
const int MINNUMBER = -32767 ;
int find_sec_max( int data[] , int count) //类似于1 4 4 4这样的序列将认为1是第二大数
{
int maxnumber = data[0] ;
int sec_max = MINNUMBER ;
for ( int i = 1 ; i < count ; i++)
{
if ( data[i] > maxnumber )
{
sec_max = maxnumber ;
maxnumber = data[i] ;
}
else
{
if ( data[i] > sec_max )
sec_max = data[i] ;
}
}
return sec_max ;
}
17 写一个在一个字符串中寻找一个子串第一个位置的函数
这个题目的一般算法比较简单我就不给出了,如果要求高效率的话请参见数据
结构中的KMP 算法,不过在笔试时间有限情况下,写出那个算法还是挺难的。
英文题目
1. Introduce yourself in English
2. What is your great advantage you think of yourself?
3. What is your drawback you think of yourself?
Maybe I will feel very tense if I make a speech in front of a lot of people.
4. How do you feel shanghai?

 

posted on 2018-10-09 16:14  priarieNew  阅读(666)  评论(0编辑  收藏  举报

导航