博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
那些常考的问答面试题(三)
阅读量:5053 次
发布时间:2019-06-12

本文共 7418 字,大约阅读时间需要 24 分钟。

48. 拆解一个整数,比如4,可以拆解成4=3+1;4=2+2;4=2+1+1;4=1+1+1+1 

首先,对一个数进行拆分后,可能又要对最后一个因子进行拆分,所以要用递归;其次,第n+1个因子是小于等于第n个因子的;再者,对最后一个因子,我可以直接输出,也可以继续拆分。
算法如下:
void print(int res[], int num)
{
    for (int i = 0; i < num; ++i)
    {
        printf("%d ", res);
    }
    printf("\n");
}
// n表示总数,m表示最大因子
void split(int n, int m)
{
    static int res[100]; //保存结果
    static int num = -1; //当前因子下标
    num++;
    //递归终止条件,为0不可再分,直接输出
    if(0 == n) 
    {
        print(res, num+1);
        num--;
        return;
    }
    else
    {
        if(n == m) 
        {
            // 不拆,直接输出
            res[num] = m;
            print(res,num+1);
            num--;
        }
        else
        {
            // 拆分出第一个
            res[num] = m;
            n = n-m;
            //最大因子不可能大于总数
            if(m>n) m = n;
            // 循环,第二个因子可以继续拆分,而且按照最大因子不同可以拆分成多个
            for (int i = m; i>=1; --i)
            {
                split(n, i);
            }
            num--;
        }    
    }
}
void Split(int n)
{
    for (int i = n-1; i>=1; i--)
    {
        split(n, i);
    }
}
唉,老了,这个小东西搞了我N久的。。。。
49. 不用库函数,实现strcpy或者memcpy等函数 
一个字节一个字节的拷过去吧,但是要考虑源内存与目标内存的重叠。
50. 内联函数的作用和缺点 
把代码直接插入到调用的地方,可以减少函数调用的次数,但是会增加代码的size,还有,如果内联失败,在每个调用的obj里,都会产生一份该函数的拷贝,这样既没有怎么减少代码的size,又没有减少函数的调用,赔了夫人又折兵。。。
51. 指针和引用的区别 
指针可以不初始化,引用必须初始化
指针可以是NULL,而引用必须引用一个实在的对象
指针可以重指向其他对象,引用一旦初始化,便不再改变
52. 友元的意义 
使被声明为友元的函数或类可以访问某个类的非共有成员。
53. 虚函数的意义 
实现多态
54. Overload, Overwrite, Override 各自的特点和意义 
Overload: 函数重载(名字相同,参数不同)
Overwrite:覆盖
Override: 虚函数重载
55. 头文件中的ifndef/define/endif 干什么用?
防止该头文件被重复引用。 
56. #i nclude <filename.h> 和#i nclude “filename.h” 有什么区别? 
#i nclude <filename.h>: 从标准库路径去寻找该文件,对于VC来说,应该还包括VC环境设置选项中的包含目录以及工程属性中指定的目录
#i nclude “filename.h”:先在当前目录查找,如果找不到,按上面那种方式寻找
57. 在C++ 程序中调用被C 编译器编译后的函数,为什么要加extern “C”?
C++语言支持函数重载,C 语言不支持函数重载。函数被C++编译后在库中的名字与C 语言的不同。C++提供了C 连接交换指定符号extern“C”来解决名字匹配问题 
58. 一个类有基类、内部有一个其他类的成员对象,构造函数的执行顺序是怎样的?
先执行基类的(如果基类当中有虚基类,要先执行虚基类的,其他基类则按照声明派生类时的顺序依次执行),再执行成员对象的,最后执行自己的。 
59. 请描述一个你熟悉的设计模式 
这个看你熟悉什么了。singleton最简单了,template method用的最多了,bridge挺炫的,command吹吹undo,redo也不错。。。。。
60. 在UML 中,聚合(aggregation)和组合(composition)有什么区别? 
其实从名字就能分别出来了。
聚合表示只是简单的聚聚,没什么本质的联系,所以这些对象的生存时间也就没什么关系了;
组合表示了更加紧密的一种关系,这些对象有着共同的生存期。
一个典型的例子是孙悟空,手臂,金箍棒的关系。。。。
61. C#和C++除了语法上的差别以外,有什么不同的地方? 
C++是直接生成可执行代码,而C#是先生成中间代码,等到第一次执行时,才由JIT(Just In Time)生成可执行的机器码。
还有就是(1) c#有垃圾自动回收机制,程序员不用担心对象的回收。(2)c#严禁使用指针,只能处理对象。如果希望使用指针,则仅可在unsafe 程序块中能使用指针。(3)c#只能单继承。(4)必须通过类名访问静态成员。不能像C++中那样,通过对象访问静态成员。(5)在子类中重写父类的虚函数时必须用关键字override,覆盖父类的方法要用关键字new 
62. New delete与malloc free 的区别 
对于类,New 和delete会调用构造,析构函数
new,delete都是能感知到类型的。new返回一个制定的类型,delete删除一个指定的类型,从而不用给定size。而malloc与free都是处理void类型的。用时时必须经过强制类型转换。
63. #define DOUBLE(x) x+x,i = 5*DOUBLE(10);i是多少?正确的声明是什么? 
I = 5*10+10 = 60 60
正确的声明是:
#define DOUBLE(x) ((x)+(x))
64. 有哪几种情况只能用intialization list 而不能用assignment? 
当类中含有const、reference 成员变量;基类的构造函数都需要参数;类中含有其他类的成员对象,而该类的构造函数都需要参数。
65. C++是不是类型安全的?
不是。两个不同类型的指针之间可以强制转换。C#是类型安全的。 
66. main 函数执行以前,还会执行什么代码?
全局对象的构造函数会在main 函数之前执行。 
67. 描述内存分配方式以及它们的区别。
(1)从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static 变量。
(2) 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集。用的是cache,速度较快但容量较小。
(3) 从堆上分配,亦称动态内存分配。程序在运行的时候用malloc 或new 申请任意多少的内存,程序员自己负责在何时用free 或delete 释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。
(4)文字常量区, 如char* p = "hello, world"就是一个例子,其内存也在程序编译的时候就已经分配好?
  一个程序除了上面这些,还有一个(5)程序代码区了。
68. 比较一下C++中static_cast 和 dynamic_cast 的区别。 
Static_cast可以显式的做一些自动转换,如一些int, char一些基础类型的转换,以及指针之间的转换。但是其不保证安全性。Dynamic_cast主要作用其实在于把一个基类指针转化为子类指针,因为这个基类指针真正指向的不一定是我们想转换的类型的对象,所以转换可能失败,dynamic_cast能够知道失败而返回NULL,而static_cast就没那么聪明了,原因是dynamic_cast会利用rtti去查找该转换是否可行.(耗费时间多点。)
69. 当一个类A 中没有生命任何成员变量与成员函数,这时sizeof(A)的值是多少,如果不是零,请解释一下编译器为什么没有让它为零。
不为零,不同的对象应该有不同的地址,假设我声明一个A的数组A a[2],如果为零,那么a[0]和a[1]的地址岂不相同了
70. 已知两个链表head1 和head2各自有序,请把它们合并成一个链表依然有序,要求用递归方法进行。 
归并排序,应该比较简单。要注意的是如果一个链表为空,那么可以简单的把另一个直接链过去了。

一个类有基类、内部有一个其他类的成员对象,构造函数的执行顺序是怎样的。(Autodesk)

class Abase
{
    public:
        Abase() { cout << "Abase construct" << endl; }
}
;
class B
{
    public:
        B() { cout << "B construct" << endl; }
}
;
class A
{
    public:
        A() { cout << "A construct" << endl; }
    
    private:
        B b;
}
;
output:
    Abase construct    
    B construct
    A construct
请描述一个你熟悉的设计模式(Autodesk)
bridge模式,将抽象的部分与它实现的部分分离,使它们可以独立的变化。
bridge模式一般使用在一个抽象部分对应多个不同的实现部分的时候。
例如:
class Shape 
{
    public:
        virtual Draw() = 0;
    private:
        Draw *_dp;
    protected:
        Shap(Draw *dp) { _dp = dp; }
        void DrawLine(int x1, int y1, int x2, int y2);
        void DrawCircle(int x, int y, int r);
}
;
class Rectrangle : public Shape
{
    public:
        Draw();
        Rectrangle(Draw* dp, int x1, int y1, int x2, int y2);
    private:
        int _x1, _y1, _x2, _y2;
}
;
Rectrangle:Rectrangle(Draw* dp, int x1, int y1, int x2, int y2) : Shape(dp)
{
    _x1 = x1, _y1 = y1, _x2 = x2, _y2 = y2;
}
Rectrangle:Draw()
{
    DrawLine(_x1, _y1, _x1, _y2);
    DrawLine(_x1, _y2, _x2, _y2);
    DrawLine(_x2, _y1, _x1, _y1);
    DrawLine(_x1, _y1, _x2, _y2);
}
class Cricle: public Shape
{
    public:
        Draw();
        Circle(Draw* dp, int x, int y, int r);
    private:
        int _x, _y, _r;
}
;
Circle:Circle(Draw* dp, int x, int y, int r) : Shape(dp)
{
    _x = x, _y = y, _r = r;
}
Circle:Draw()
{
    DrawCircle(_x, _y, _r);
}
Class Draw
{
    public:
        virtual void DrawLine(int x1, int y1, int x2, int y2) = 0;
        virtual void DrawCricle(int x, int y, int r) = 0;
}
;
Class V1Draw : public Draw
{
    public:
        void DrawLine(int x1, int y1, int x2, int y2);
        void DrawCricle(int x, int y, int r);    
}
;
Class V2Draw : public Draw
{
    public:
        void DrawLine(int x1, int y1, int x2, int y2);
        void DrawCricle(int x, int y, int r);    
}
;
在UML 中,聚合(aggregation)和组合(composition)有什么区别 (Autodesk)
聚合的特点是比较松的包含关系,如飞机场与飞机的关系,它是指一类事物的集聚关系。每个类都可以单独成为一个个体。
组合的特点是比较强的耦合关系,属于包容关系,比如A是由B,C组合,那么C是A的一部份。
C#和C++除了语法上的差别以外,有什么不同的地方?
1.c#不支持多重继承
2.c#在安全代码中不支持指针
3.c#具有自动垃圾回收机制
new delete 与malloc free 的区别 ( Autodesk)
1.new是关键字,malloc是函数
2.new调用对象的构造函数, malloc只分配内存空间
3.new的内存分配算法与malloc的不同
#define DOUBLE(x) x+x (Autodesk)
i = 5*DOUBLE(10); i 是多少?正确的声明是什么?
i = 5*x + x= 5*10 + 10 = 60;
#define DOUBLE(x) ((x)+(x))
有哪几种情况只能用intialization list 而不能用assignment?
1.初始化基类的成员数据
2.初始化const,referance的成员对象。
3.类中包含的其他类对象,并且该对象需要参数构造。
C++是不是类型安全的? (Autodesk)
不是。
描述内存分配方式以及它们的区别
1.静态内存区域,用于分配全局变量,静态变量和常量,编译期间
2.堆,用于动态分配内存,在调用malloc时,运行期间
3.栈,用于分配局部变量,编译期间
比较一下C++中static_cast 和 dynamic_cast 的区别
1.static_cast编译时进行类型转换检查, dynamic_cast在运行时进行类型转换
2.static_cast有点类似与c中的强制类型转换,dynamic_cast是沿着继承层次进行安全的类型转换,
Struct 和class 的区别 (Autodesk)
1.作用域不同,struct的成员默认都是public; class中的成员默认为private
2.struct中不存在多态和虚拟继承。
3.class中的对象布局并不一定与声明次序一致。
当一个类A 中没有生命任何成员变量与成员函数,这时sizeof(A)的值是多少,如果不是零,请解释一下编译器为什么没有让它为零。(Autodesk)
1.等于1
2.为了在将来能实现对象的内存分配,编译器给空类提供了一个字节的占位符!
 main 函数执行以前,还会执行什么代码? (Autodesk)
答案:全局对象的构造函数会在main 函数之前执行。
类成员函数的重载、覆盖和隐藏区别
答案:
成员函数被重载的特征:
(1)相同的范围(在同一个类中);
(2)函数名字相同;
(3)参数不同;
(4)virtual 关键字可有可无。
覆盖是指派生类函数覆盖基类函数,特征是:
(1)不同的范围(分别位于派生类与基类);
(2)函数名字相同;
(3)参数相同;
(4)基类函数必须有virtual 关键字。
“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下:
(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。
(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual 关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)
(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;
}
请自己执行一下看看。

转载于:https://www.cnblogs.com/bertrandwdx/archive/2013/01/15/2861569.html

你可能感兴趣的文章
log4j配置
查看>>
linux 配置SAN存储-IPSAN
查看>>
java学习笔记之String类
查看>>
pymysql操作mysql
查看>>
Linux服务器删除乱码文件/文件夹的方法
查看>>
牛腩记账本core版本源码
查看>>
Word Break II
查看>>
UVA 11082 Matrix Decompressing 矩阵解压(最大流,经典)
查看>>
jdk从1.8降到jdk1.7失败
查看>>
一些关于IO流的问题
查看>>
mongo备份操作
查看>>
8 -- 深入使用Spring -- 3...1 Resource实现类InputStreamResource、ByteArrayResource
查看>>
硬件笔记之Thinkpad T470P更换2K屏幕
查看>>
一个关于vue+mysql+express的全栈项目(六)------ 聊天模型的设计
查看>>
【知识库】-数据库_MySQL 的七种 join
查看>>
.net 写文件上传下载webservice
查看>>
noSQL数据库相关软件介绍(大数据存储时候,必须使用)
查看>>
iOS开发——缩放图片
查看>>
HTTP之URL的快捷方式
查看>>
满世界都是图论
查看>>