首页 > 代码库 > C++面试试题汇总1

C++面试试题汇总1

1.C和C++的主要区别是什么?

答:1.C++语言包括过程性语言部分和类部分,过程性语言部分与C并无本质的差别,类部分是C语言中所没有的,它是面向对象程序设计的主体。

2.程序设计方法上已从结构化程序设计走向面向对象程序设计了.

2.结构程序设计和面向对象程序设计的概念

结构化程序设计的主要思想是功能分解并逐步求精。数据与程序分开存储,编程的主要技巧在于追踪哪些函数调用哪些函数,哪些数据发生了变化。

面向对象程序设计的本质是把数据和处理数据的过程当成一个整体----对象。(对象是一种特殊变量----像结构体变量、又增加了相关的操作行为)

面向对象程序设计的实现需要封装和数据隐藏技术、继承和重用技术、多态性技术

3.什么是类和对象?

类是一组性质相同的对象的程序描述,它由概括了一组对象共同性质的数据和函数组成。是封装的基本单元.

对象是构成世界的一个独立单位,它具有自己的静态特征(状态)和动态特征(操作)。静态特征即可以用某种数据来描述的特征,动态特征即对象所表现的行为或对象所具有的功能。

类与对象的关系:类给出了属于该类的全部对象的抽象定义,而对象则是符合这种定义的一个实体。所以,一个对象又称作类的一个实例(instance)。对象是类的实例,类定义了属于该类的所有对象的共同特性。

4. 面向对象程序设计的三大特征是什么?

       1.封装(encapsulation): 封装是面向对象方法的一个重要原则。它有两个涵义:第一个涵义是,把对象的全部属性和全部服务结合在一起,形成一个不可分割的独立单位(即对象)。第二个涵义也称作“信息隐蔽”,即尽可能隐蔽对象的内部细节,对外形成一个边界(或者说形成一道屏障),只保留有限的对外接口使之与外部发生联系。这主要是指对象的外部不能直接地存取对象地属性,只能通过几个允许外部使用地服务与对象发生联系。

      2.继承(inheritance): (单继承和多继承)子类可以继承父类中的属性和操作,也可以定义自己的属性和操作

       3.多态性(polymorphism):在一般类中定义的属性或操作被特殊类继承之后,可以具有不同的数据类型或表现出不同的行为。这使得同一个属性或操作名在一般类及其各个特殊类中具有不同的语义。

5.类的组成:

class是定义类的关键字。<类名>是一个标识符,用于惟一标识一个类。一对大括号内是类的说明部分,说明该类的所有成员。类的成员包括数据成员和成员函数两部分。类的成员从访问权限上分有以下三类:公有的(public)、私有的(private)和保护的(protected),其中默认为private权限。

1.公有的成员可以被程序中的任何代码访问;

2.私有的成员只能被类本身的成员函数及友元类的成员函数访问,其他类的成员函数,包括其派生类的成员函数都不能访问它们;

3.保护的成员与私有成员类似,只是除了类本身的成员函数和说明为友元类的成员函数可以访问保护成员外,该类的派生类的成员也可以访问。

6.结构体和类的区别是什么?

结构和类的唯一区别是:在未指定访问权限时,结构中的成员被默认为公有的而类中的成员被默认为私有的。

7.类对象的定义方法和对象成员的表示方法

对象的定义方法: <类名><对象名表>;

对象成员的表示方法:<对象名>.<成员名>这里的“.”是一个运算符,该运算符的功能是表示对象的成员。或者指向对象的指针的成员表示如下:<对象指针名>-><成员名>

8.构造函数和析构函数

(1)构造函数是一种用于创建对象特殊的成员函数,当创建对象时,系统自动调用构造函数,不能在程序中直接调用。构造函数名与类名相同,一个类可以拥有多个构造函数(重载),构造函数可以有任意类型的参数,但不能具有返回类型。

(2)析构函数名字为符号“~”加类名,析构函数没有参数和返回值。一个类中只可能定义一个析构函数,所以析构函数不能重载。默认析构函数是一个空函数

(3)使用构造函数的限制:不能被继承,不能说明为虚函数,不能显式调用,不能取构造函数的地址。

9.C++程序的内存布局

C++程序的内存格局通常分为四个区:

(1)全局数据区(data area):存放全局变量、静态数据、常量。

(2)代码区(code area):存放类成员函数、其他函数代码。    

(3)栈区(stack area):存放局部变量、函数参数、返回数据、返回地址。

(4)堆区 (heap area) :自由存储区。

10.拷贝构造函数

       当构造函数的参数为自身类的引用时,这个构造函数称为拷贝构造函数。拷贝构造函数的功能是用一个已有对象初始化一个正在建立的同类对象。

11.this指针

当一个成员函数被调用时,自动向它传递一个隐含的参数,该参数是一个指向这个函数成员所在的对象的指针。成员函数中可以用this关键字来引用该指针。this指针的类型就是成员函数所属的类的类型。当调用成员函数时,它被初始化为被调用函数所在的类实例的地址。

this指针只能在类的成员函数中使用,它指向该成员函数被调用的对象。this指针一般用于返回当前对象自身。this指针大量用于运算符重载成员函数设计中。静态成员函数没有this指针。

12.运算符重载

运算符的重载形式有两种:重载为类的成员函数和重载为类的友元函数。

<函数类型> operator <运算符>(<形参表>)或friend <函数类型> operator <运算符>(<形参表>)

当运算符重载为类的成员函数时,函数的参数个数比原来的运算数个数要少一个(后缀++、--除外);当重载为类的友元函数时,参数个数与原运算数的个数相同。

单目运算符最好重载为成员函数,而双目运算符则最好重载为友元函数。

在C++中,单目运算符有++和--(后缀有一个int型的参数,而前缀没有)

13. C++中函数重写和重载有何区别?

重写Overriding是父类与子类之间多态性的一种表现,重载Overloading是一个类中多态性的一种表现。如果在子类中定义某方法与其父类有 相同的名称和参数,我们说该方法被重写 (Overriding)。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被“屏蔽”了。如果在一个类中定义了多个同名的方 法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载(Overloading)。Overloaded的方法是可以改变返回值的类型。

 

继承方式

基类特性

派生类特性

公有继承

 

Public

Public

Protected

Protected

Private

Private

私有继承

 

Public

Private

Protected

Private

Private

不可访问

保护继承

 

Public

Protected

Protected

Protected

Private

不可访问

 14.继承的基本知识

①单继承的定义格式如下:

class<派生类名> :<继承方式><基类名>

{     public:members;//派生类新定义成员

Private:members;

Protected:members;

};

(1)在公有继承时,派生类的对象可以访问基类中的公有成员;派生类的成员函数可以访问基类中的公有成员和保护成员。这里,一定要区分清楚派生类的对象和派生类中的成员函数对基类的访问是不同的。

(2)在私有继承时,基类的成员只能由直接派生类访问,而无法再往下继承。

(3)对于保护继承方式,这种继承方式与私有继承方式的情况相同。两者的区别仅在于对派生类的成员而言,对基类成员有不同的可访问性。

(4)对于基类中的私有成员,只能被基类中的成员函数和友元函数所访问,不能被其他的函数访问。

②派生类对基类成员可以有不同的访问方式:

       派生类可以覆盖基类成员

       派生类不能访问基类私有成员

基类的公有段和保护段成员访问权对派生类保持不变(公有继承)

基类的公有段和保护段成员成为派生类的私有成员(私有继承)

    ③单继承中的构造函数和析构函数

A.构造函数不能够被继承。派生类构造函数的调用顺序如下:

  (1)调用基类的构造函数,调用顺序按照它们继承时说明的顺序。

  (2)调用子对象类的构造函数,调用顺序按照它们在类中说明的顺序。

 (3)派生类构造函数体中的内容。

B.析构函数也不能被继承,因此在执行派生类的析构函数时,基类的析构函数也将被调用。执行顺序是先执行派生类的析构函数,再执行基类的析构函数,其顺序与执行构造函数时的顺序正好相反。

  ④赋值兼容规则

<!--[if !supportLists]-->(1)       <!--[endif]-->派生类的对象可以赋值给基类的对象。

<!--[if !supportLists]-->(2)       <!--[endif]-->派生类的对象可以初始化基类的引用

<!--[if !supportLists]-->(3)       <!--[endif]-->派生类的对象的地址可以赋给指向基类的指针。

15.多态性与虚函数

C++的多态性具体体现在运行和编译两个方面,在程序运行时的多态性通过继承和虚函数来体现,而在程序编译时多态性体现在函数和运算符的重载上。

重载(函数名相同、参数不同、参数类型不同、返回值无影响)

虚函数是在基类中冠以关键字 virtual 的成员函数。它提供了一种接口界面。虚函数可以在一个或多个派生类中被重定义。

虚函数的重载函数仍是虚函数。

在派生类重定义虚函数时必须有相同的函数原型,包括返回类型,函数名、参数个数、参数类型的顺序必须相同。虚函数必须是类的成员函数。析构函数可以是虚函数,但构造函数不能为虚函数。

纯虚函数:在许多情况下,在基类中不能给出有意义的虚函数定义,这时可以把它说明成纯虚函数,把它的定义留给派生类来做。定义纯虚函数的一般形式为:

class 类名{virtual 返回值类型 函数名(参数表) = 0;};

抽象类:如果一个类中至少有一个纯虚函数,那么这个类被成为抽象类(abstract class)。抽象类中不仅包括纯虚函数,也可包括虚函数。抽象类中的纯虚函数可能是在抽象类中定义的,也可能是从它的抽象基类中继承下来且重定义的。

抽象类有一个重要特点,即抽象类必须用作派生其他类的基类,而不能用于直接创建对象实例。抽象类不能直接创建对象的原因是其中有一个或多个函数没有定义,但仍可使用指向抽象类的指针支持运行时多态性。

16.C++中异常处理的实现

    C++语言异常处理机制的基本思想是将异常的检测与处理分离。

    用3个保留字实现:throw、try和catch。

被调用函数直接检测到异常条件的存在并使用throw引发一个异常(注意,C++语言的异常是由程序员控制引发的,而不是由计算机硬件或程序运行环境控制的);在上层调用函数中使用try检测函数调用是否引发异常,检测到的各种异常由catch捕获并作相应处理。

17. 函数指针与指针函数的区别

     函数指针是一个指向函数的指针,而指针函数只是说明他是一个返回值为指针的函数。

   1、在程序运行中,函数代码是程序的算法指令部分,它们和数组一样也占用存储空间,都有相应的地址。可以使用指针变量指向数组的首地址,也可以使用指针变量指向函数代码的首地址,指向函数代码首地址的指针变量称为函数指针。其函数指针的定义如下:函数类型 (*指针变量名)(形参列表);

int    (*f)(int x);double (*ptr)(double x)

定义函数指针时请注意事项

       1、函数指针和它指向的函数的参数个数和类型都应该是—致的

       2、函数指针的类型和函数的返回值类型也必须是一致的。

函数指针的使用示例:

int func(int x);     /* 声明一个函数 */int (*f) (int x);    /* 声明一个函数指针 */f=func;              /* 将func函数的首地址赋给指针f */

 

2、一个函数不仅可以带回一个整型数据的值,字符类型值和实型类型的值,还可以带回指针类型的数据,使其指向某个地址单元。返回指针的函数称为指针函数。指针函数的定义如下:类型标识符    *函数名(参数表)

 int *f(x,y);

 指针函数使用示例:

【例】将字符串1(str1)复制到字符串2(str2),并输出字符串2.#include "stdio.h"main(){char *ch(char *,char *);    char str1[]="I am glad to meet you!";    char str2[]="Welcom to study C!";    printf("%s",ch(str1,str2));}char *ch(char *str1,char *str2){int i;    char *p;    p=str2    if(*str2==NULL) exit(-1);    do{ *str2=*str1;        str1++;        str2++;    }while(*str1!=NULL);    return(p);}

18. 不带参数和void参数的区别

   对不带任何参数的函数来说(注意:不带任何参数和void参数是不同概念),C语言和C++对此有不同的规定。例如一个参数 void f(){}
1. 在C语言中,函数原型中不带任何参数的函数,被认为可以在调用时传任何参数进去(没错,正好是相反的),即f()、f(1)、f("abcd")全都是可通过编译的。
2. 在C++语言中,函数原型中不带任何参数的函数,被认为是一个参数为void的函数。也就是说,void f(){}实际上被认为是void f(void){},在实际调用时,不允许传参数进去。

C++面试试题汇总1