【原文链接】

http://www.cnblogs.com/hellogiser/p/100-interview-questions-of-cplusplus-basics-1-10.html

题目1

我们可以用static修饰一个类的成员函数,也可以用const修饰类的成员函数(写在函数的最后表示不能修改成员变量,不是指写在前面表示返回值为常量)。请问:能不能同时用static和const修饰类的成员函数?

分析

不可以。C++编译器在实现const的成员函数的时候为了确保该函数不能修改类的实例的状态,会在函数中添加一个隐式的参数const this*。但当一个成员为static的时候,该函数是没有this指针的。我们也可以这样理解:两者的语意是矛盾的。static是针对类型,与类的实例没有关系;而const是针对实例,确保函数不能修改实例的状态。因此不能同时用它们。


题目2

运行下面的代码,输出是什么?

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 
class A
{
};

class B
{
public:
    B() {}
    ~B() {}
};

class C
{
public:
    C() {}
    virtual ~C() {}
};

int _tmain(int argc, _TCHAR *argv[])
{
    printf("%d, %d, %d\n", sizeof(A), sizeof(B), sizeof(C));
    ;
}

分析

答案是1, 1, 4。

class A是一个空类型,它的实例不包含任何信息,本来求sizeof应该是0。但当我们声明该类型的实例的时候,它必须在内存中占有一定的空间,否则无法使用这些实例。至于占用多少内存,由编译器决定。Visual Studio 2008中每个空类型的实例占用一个byte的空间。

class B在class A的基础上添加了构造函数和析构函数。由于构造函数和析构函数的调用与类型的实例无关(调用它们只需要知道函数地址即可),在它的实例中不需要增加任何信息。所以sizeof(B)和sizeof(A)一样,在Visual Studio 2008中都是1。

class C在class B的基础上把析构函数标注为虚拟函数。C++的编译器一旦发现一个类型中有虚拟函数,就会为该类型生成虚函数表,并在该类型的每一个实例中添加一个指向虚函数表的指针。在32位的机器上,一个指针占4个字节的空间,因此sizeof(C)是4。


题目3

运行下面中的代码,得到的结果是什么?

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 
#include "stdafx.h"

class A
{
private:
    int m_value;

public:
    A(int value)
    {
        m_value = value;
    }
    void Print1()
    {
        printf("hello world");
    }
    void Print2()
    {
        printf("%d", m_value);
    }
};

int _tmain(int argc, _TCHAR *argv[])
{
    A *pA = NULL;
    pA->Print1(); // "hello world"
    pA->Print2(); // ERROR

;
}

分析

答案是Print1调用正常,打印出hello world,但运行至Print2时,程序崩溃。调用Print1时,并不需要pA的地址,因为Print1的函数地址是固定的。编译器会给Print1传入一个this指针,该指针为NULL,但在Print1中该this指针并没有用到。只要程序运行时没有访问不该访问的内存就不会出错,因此运行正常。在运行print2时,需要this指针才能得到m_value的值。由于此时this指针为NULL,因此程序崩溃了。


题目4

运行下面中的代码,得到的结果是什么?

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 
class A
{
private:
    int m_value;

public:
    A(int value)
    {
        m_value = value;
    }
    void Print1()
    {
        printf("hello world");
    }
    virtual void Print2()
    {
        printf("hello world");
    }
};

int _tmain(int argc, _TCHAR *argv[])
{
    A *pA = NULL;
    pA->Print1();
    pA->Print2();

;
}

【分析】

答案是Print1调用正常,打印出hello world,但运行至Print2时,程序崩溃。Print1的调用情况和上面的题目一样,不在赘述。由于Print2是虚函数。C++调用虚函数的时候,要根据实例(即this指针指向的实例)中虚函数表指针得到虚函数表,再从虚函数表中找到函数的地址。由于这一步需要访问实例的地址(即this指针),而此时this指针为空指针,因此导致内存访问出错。


题目5

静态成员函数能不能同时也是虚函数?

【分析】

答案是不能。调用静态成员函数不要实例,但调用虚函数需要从一个实例中获取指向虚函数表的指针以得到函数的地址,因此调用虚函数需要一个实例。两者相互矛盾。


题目6

运行下列C++代码,输出什么?

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 
#include "stdafx.h"

struct Point3D
{
    int x;
    int y;
    int z;
};

int _tmain(int argc, _TCHAR *argv[])
{
    Point3D *pPoint = NULL;
    int offset = (int)(&pPoint->z);

printf("%d", offset); // 8
;
}
/*
+       pPoint  0x00000000 {x=??? y=??? z=??? } Point3D *
+       &pPoint->x  0x00000000  int *
+       &pPoint->y  0x00000004  int *
+       &pPoint->z  0x00000008  int *
*/

【分析】

输出8。&(pPoint->z)的语意是求pPoint中变量z的地址(pPoint的地址0加z的偏移量8),并不需要访问pPoint指向的内存。只要不访问非法的内存,程序就不会出错。


题目7

运行下列C++代码,输出什么?

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
 
#include "stdafx.h"

class A
{
public:
    A()
    {
        Print();
    }
    ~A()
    {
        printf("A is erased.\n");
    }
    virtual void Print()
    {
        printf("A is constructed.\n");
    }
};

class B: public A
{
public:
    B()
    {
        Print();
    }
    ~B()
    {
        printf("B is erased.\n");
    }
    virtual void Print()
    {
        printf("B is constructed.\n");
    }
};

int _tmain(int argc, _TCHAR *argv[])
{
    A *pA = new B();
    delete pA;

B *pB = new B();
    delete pB;

;
}
/*
A is constructed.
B is constructed.
A is erased.

A is constructed.
B is constructed.
B is erased.
A is erased.
*/

【分析】

输出结果如上所示。


【题目8】

运行下列C#代码,输出是什么?

 C# Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 
namespace ChangesOnString
{
    class Program
    {
        static void Main(string[] args)
        {
            String str = "hello";
            str.ToUpper();
            str.Insert(, " WORLD");

Console.WriteLine(str);
        }
    }
}

【分析】

输出是hello。由于在.NET中,String有一个非常特殊的性质:String的实例的状态不能被改变。如果String的成员函数会修改实例的状态,将会返回一个新的String实例。改动只会出现在返回值中,而不会修改原来的实例。所以本题中输出仍然是原来的字符串值hello。如果试图改变String的内容,改变之后的值可以通过返回值拿到。用StringBuilder是更好的选择,特别是要连续多次修改的时候。如果用String连续多次修改,每一次修改都会产生一个临时对象,开销太大。


【题目9】

在C++和C#中,struct和class有什么不同?

【分析】

在C++中,如果没有标明函数或者变量是的访问权限级别,在struct中,是public的;而在class中,是private的。

在C#中,如果没有标明函数或者变量的访问权限级别,struct和class中都是private的。

struct和class的区别是:struct定义值类型,其实例在栈上分配内存;class定义引用类型,其实例在堆上分配内存。


【题目10】

运行下图中的C#代码,输出是什么?

 C# Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 
namespace StaticConstructor
{
    class A
    {
        public A(string text)
        {
            Console.WriteLine(text);
        }
    }

class B
    {
        static A a1 = new A("a1");
        A a2 = new A("a2");

static B()
        {
            a1 = new A("a3");
        }

public B()
        {
            a2 = new A("a4");
        }
    }

class Program
    {
        static void Main(string[] args)
        {
            B b = new B();
        }
    }
}

【分析】

打印出四行,分别是a1、a3、a2、a4。

在调用类型B的代码之前先执行B的静态构造函数。静态函数先初始化类型的静态变量,再执行静态函数内的语句。因此先打印a1再打印a3。接下来执行B b = new B(),即调用B的普通构造函数。构造函数先初始化成员变量,在执行函数体内的语句,因此先后打印出a2、a4。

【参考】

http://zhedahht.blog.163.com/blog/static/254111742011012111557832/

【原文链接】

http://www.cnblogs.com/hellogiser/p/100-interview-questions-of-cplusplus-basics-1-10.html

C++基础知识面试精选100题系列(1-10题)[C++ basics]的更多相关文章

  1. C++基础知识面试精选100题系列(11-20题)[C++ basics]

    [原文链接] http://www.cnblogs.com/hellogiser/p/100-interview-questions-of-cplusplus-basics-11-20.html [题 ...

  2. C++基础知识面试精选100题系列(21-30)[C++ basics]

    [本文链接] http://www.cnblogs.com/hellogiser/p/100-interview-questions-of-cplusplus-basics-21-30.html [题 ...

  3. C#基础知识面试经典[整理]

    个人网站:http://www.51pansou.com .net视频下载:.net视频教程 .net源码下载:.net源码 当初学 C# 时是找个人大概问了一下数据类型和分支语句就开始做项目了.这两 ...

  4. Leetcode第1题至第10题 思路分析及C++实现

    笔者按照目录刷题,对于每一道题,力争使用效率最高(时间复杂度最低)的算法,并全部通过C++代码实现AC.(文中计算的复杂度都是最坏情况复杂度) 因为考虑到大部分读者已经在Leetcode浏览过题目了, ...

  5. .Net及C#基础知识,面试宝典

    作为你一.Net和C#开发这些知识,你是否掌握了,你是否算的上一名入门的程序员? 技术不行并不可怕,可怕的是你不知道自己还需做哪一方面的提升,本篇文字本人的一些面试时所经常涉及的问题,并且在网上收集了 ...

  6. java基础知识面试总结-部分

    前言 在平时的工作学习中,自己对微服务和springboot基础理论知识关注比较少,在面试中对于面试官的问题,很多基本都不能够达到精准,全面:现将自己面试中的问题做以总结: 1.谈谈你对微服务架构的认 ...

  7. BAT机器学习面试1000题系列(41-45题)

    41.线性分类器与非线性分类器的区别以及优劣 如果模型是参数的线性函数,并且存在线性分类面,那么就是线性分类器,否则不是.常见的线性分类器有:LR,贝叶斯分类,单层感知机.线性回归常见的非线性分类器: ...

  8. MySQL基础知识面试与答案

    1.Mysql 的存储引擎,myisam和innodb的区别. 答: 1.MyISAM 是非事务的存储引擎,适合用于频繁查询的应用.表锁,不会出现死锁,适合小数据,小并发. 2.innodb是支持事务 ...

  9. 【校招面试 之 C/C++】第10题 C++不在构造函数和析构函数中调用虚函数

    1.不要在构造函数中调用虚函数的原因 在概念上,构造函数的工作是为对象进行初始化.在构造函数完成之前,被构造的对象被认为“未完全生成”.当创建某个派生类的对象时,如果在它的基类的构造函数中调用虚函数, ...

随机推荐

  1. jquery 在 table 中修改某行值

    修改 table 中某行的的方法步骤如下: 1.选择要修改的行,事件触发,比如我的 双击某行时修改 2.将要修改的行,替换为input,原先的列中的值,需要放到对应的input中作为默认值 3.修改完 ...

  2. 决策树笔记:使用ID3算法

    决策树笔记:使用ID3算法 决策树笔记:使用ID3算法 机器学习 先说一个偶然的想法:同样的一堆节点构成的二叉树,平衡树和非平衡树的区别,可以认为是"是否按照重要度逐渐降低"的顺序 ...

  3. BZOJ1816 [Cqoi2010]扑克牌

    Description 你有n种牌,第i种牌的数目为ci.另外有一种特殊的 牌:joker,它的数目是m.你可以用每种牌各一张来组成一套牌,也可以用一张joker和除了某一种牌以外的其他牌各一张组成1 ...

  4. Eclips将lib打入war中

    在项目的属性, java build path -> Libraries -> Add library.. -> Web app Libraries .即可. 在属性中, Deplo ...

  5. 轻量级应用开发之(07) UIPickerView使用

    #import "ViewController.h" @interface ViewController ()<UIPickerViewDataSource,UIPicker ...

  6. RONOJ 6今明的预算方案(有依赖的背包)

    题目描述 金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房间.更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过N元钱就行”.今 ...

  7. Java_观察者模式(Observable和Observer)

    http://blog.csdn.net/tianjf0514/article/details/7475164/ 一.观察者模式介绍 在Java中通过Observable类和Observer接口实现了 ...

  8. Spring IoC、DI入门小程序

    Alt+/智能提示xml配置文件节点及属性:在接口上使用Ctrl+T可以提示其实现类 一.IoC控制反转(将创建对象的权利交给spring)入门小程序 1.引入jar包 2.工程基本结构 3.新建Us ...

  9. javaweb学习总结(三十)——EL函数库

    一.EL函数库介绍 由于在JSP页面中显示数据时,经常需要对显示的字符串进行处理,SUN公司针对于一些常见处理定义了一套EL函数库供开发者使用. 这些EL函数在JSTL开发包中进行描述,因此在JSP页 ...

  10. C文件操作(全)

    引用自:http://www.cnblogs.com/whiteyun/archive/2009/08/08/1541822.html 文件 文件的基本概念 所谓“文件”是指一组相关数据的有序集合. ...