C++面试题

1.char c = '\72'; 中的 \72 代表一个字符,72 是八进制数,代表 ASCII 码字符 :。2.10*a++ 中 a 先进行乘法运算再自增。3.conststatic 的作用 static 关键字:1)函数体内 static 变量的作用范围为函数体。不同于 auto 变量。该变量的内存只被分配一次。因此其值在下次调用时仍维持上次的值。2)在模块内的 static 全局变量可以被模块内的所有函数访问。但不能被模块外的其他函数访问。3)在模块内的 static 函数只可被这一模块内的其它函数调用。这个函数的使用范围被限制在声明它的模块内。4)在类中的 static 成员变量属于整个类所有,对类的所有对象只有一份复制。5)在类中的 static 成员函数属于整个类所有,这个函数不接受 this 指针,因而只能访问类的 static 成员变量。const 关键字:1)欲阻止一个变量被改变,可以使用 const 关键字。在定义该 const 变量时,通常需要对它进行初始化。因为以后就没有机会再改变它了。2)对指针来说,可以指定指针的本身为 const,也可以指定指针所指向的数为 const。或二者同时为 const。3)在一个函数的声明中,const 可以修饰形参,表明它是一个输入参数。在函数内不能改变其值。4)对于类的成员函数,若指定其为 const 类型。则表明其是一个常量函数。不能修改类的成员变量。5)对于类的成员函数,有时候必须指定其返回值为 const 类型。以使得其返回值不为”左值”。4.注意 sizeof 不是函数而是运算符,所以在计算变量所占用空间大小时,括号是可以省略的,但在计算类型大小时括号则不能省略,比如 int i = 0;sizeof int 是错误的。5.易误解:如果 int a[5] 那么 a 与&a 是等价的,因为两者地址相同。解答:一定要注意 a&a 是不一样的,虽然两者地址相同,但意义不一样,&a 是整个数组对象的首地址,而 a 是数组首地址,也就是 a[0] 的地址,a 的类型是 int[5],a[0] 的类型是 int,因此 &a+1 相当于 a 的地址值加上 sizeof(int) * 5,也就是 a[5],下一个对象的地址,已经越界了,而 a+1 相当于 a 的地址加上 sizeof(int),即 a[1] 的地址。6.可作为函数重载判断依据的有:参数个数、参数类型、const 修饰符;不可以作为重载判断依据的有:返回类型。7.程序输出题:

int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int *p = &(a + 1)[3];
printf("%d\n", *p);

输出:5 说明:因为 a+1 指向 a 的第二个元素,[3] 表示再向后移动 3 个元素。8.程序输出题:

char str1[] =  "abc";
char str2[] = "abc";

const char str3[] = "abc";
const char str4[] = "abc";

const char *str5 = "abc";
const char *str6 = "abc";

char *str7 = "abc";
char * str8 = "abc";

std::cout << (str1 == str2) << std::endl;
std::cout << (str3 == str4) << std::endl;
std::cout << (str5 == str6) << std::endl;
std::cout << (str7 == str8) << std::endl;

输出:0 0 1 1 可以发现 str1->str4 中的内容是存在栈上,地址各不相同,而 str5->str8 的内容都是存储在常量区,所以地址都相同。注意:上面打印的是字符串 “abc”的地址,下面打印的是 str1 变量的地址。9.C 的结构体和 C++结构体的区别(1)C 的结构体内不允许有函数存在,C++允许有内部成员函数,且允许该函数是虚函数。所以 C 的结构体是没有构造函数、析构函数、和 this 指针的。(2)C 的结构体对内部成员变量的访问权限只能是 public,而 C++允许 public,protected,private 三种。(3)C 语言的结构体是不可以继承的,C++的结构体是可以从其他的结构体或者类继承过来的。 以上都是表面的区别,实际区别就是面向过程和面向对象编程思路的区别:C 的结构体只是把数据变量给包裹起来了,并不涉及算法。而 C++是把数据变量及对这些数据变量的相关算法给封装起来,并且给对这些数据和类不同的访问权限。C 语言中是没有类的概念的,但是 C 语言可以通过结构体内创建函数指针实现面向对象思想。10.如何在类中定义常量成员并为其初始化?解答:只能在初始化列表里对 const 成员初始化,像下面这样:

class Cbook {
public:
    const double m_prices;
    Cbook():m_prices(8.8) {}
};

下面的做法是错误的:

class Cbook {
public:
    const double m_prices;
    Cbook() {
            m_prices = 8.8;
    }
};

11.在定义类的成员函数时使用 mutable 关键字的作用是什么?解答:当需要在 const 方法中修改对象的数据成员时,可以在数据成员前使用 mutable 关键字,防止出现编译出错。例子如下:

  1. 构造函数、拷贝构造函数、析构函数的调用点和顺序问题,如下面这个例子输出是什么?
    解答:注意拷贝构造函数在对象作为函数参数传递时被调用,注意是对象实例而不是对象引用。因此该题输出如下:引申:拷贝构造函数在哪些情况下被调用?(1)函数的参数为类对象且参数采用值传递方式;(2)将类对象做为函数的返回值。
  2. C++中的 explicit 关键字有何作用?
    解答:禁止将构造函数作为转换函数,即禁止构造函数自动进行隐式类型转换。例如 CBook 中只有一个参数 m_price,在构建对象时可以使用 CBook c = 9.8 这样的隐式转换,使用 explicit 防止这种转换发生。
  3. 在 C++中,如果确定了某一个构造函数的创建过程,在该构造函数中如果调用了其它重载的构造函数,它将不会执行其它构造函数的初始化列表部分代码,而是执行函数体代码,此时已经退化成普通函数了。例子说明如下:
  4. 静态数据成员只能在全局区域进行初始化,而不能在类体中进行且静态数据成员不涉及对象,因此不受类访问限定符的限制。
  5. C++中可以重载的运算符:new/delete、new[]/delete[]、++ 等。
    不可以重载的运算符:.、::、?:、sizeof、typeid、**,不能改变运算符的优先级。引申:重载++和–时是怎么区分前缀++和后缀++的?例如当编译器看到++a 先自增时,它就调用 operator++(a);但当编译器看到 a++时,它就调用 operator++(a, int)。即编译器通过调用不同的函数区别这两种形式。
  6. C++的多态性分为静态多态和动态多态。
    静态多态性:编译期间确定具体执行哪一项操作,主要是通过函数重载和运算符重载来实现的;动态多态性:运行时确定具体执行哪一项操作,主要是通过虚函数来实现的。18.虚函数原理考点,例如下面程序的输出是什么?
    class A {
    public:
    virtual void funa();
    virtual void funb();
    void func();
    static void fund();
    static int si;
    private:
    int i;
    char c;
    };
    sizeof(A) = ?
    解答:关于类占用的内存空间,有以下几点需要注意:(1)如果类中含有虚函数,则编译器需要为类构建虚函数表,类中需要存储一个指针指向这个虚函数表的首地址,注意不管有几个虚函数,都只建立一张表,所有的虚函数地址都存在这张表里,类中只需要一个指针指向虚函数表首地址即可。(2)类中的静态成员是被类所有实例所共享的,它不计入 sizeof 计算的空间(3)类中的普通函数或静态普通函数都存储在栈中,不计入 sizeof 计算的空间(4)类成员采用字节对齐的方式分配空间答案:1619.虚继承的作用是什么?在多继承中,子类可能同时拥有多个父类,如果这些父类还有相同的父类, 那么在子类中就会有多份祖先类。例如,类 B 和类 C 都继承与类 A,如果类 D 派生于 B 和 C,那么类 D 中就会有两份 A。为了防止在多继承中子类存在重复的父类情况,可以在父类继承时使用虚函数,即在类 B 和类 C 继承类 A 时使用 virtual 关键字,例如:
    class B : virtual public A {};
    class C : virtual public A {};
    注:因为多继承会带来很多复杂问题,因此要慎用。

   转载规则


《C++面试题》 吴杭沉 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
使用++i还是i++ 使用++i还是i++
我们经常使用 for 循环来遍历东西,循环变量可以前自增也可以后自增,发现对遍历结果没啥影响,但是该如何选择呢?我们应该尽量使用前自增运算符而不是后自增运算符,即用 ++Iter 代替 Iter++。前缀和后缀形式之间的区别是众所周知的。我
2018-08-04
下一篇 
C++细说sizeof C++细说sizeof
摘要sizeof 的作用非常简单:求对象或者类型的大小。然而 sizeof 又非常复杂,它涉及到很多特殊情况,总结出了 sizeof 的 9 个特性:(1)sizeof 不能求得 void 类型的长度;(2)sizeof 能求得 void
2018-07-29
  目录