【华师】C++简答题汇总

简答题

斜体和代码块都是了解即可

面向对象四大特征:封装、抽象、继承、多态

对象

客观世界中的任何一个事物都可以视作一个对象。任何一个对象都己有两个要素:属性和行为。属性是对象本身的性质,而行为是对象的功能。C++中每个对象都是由数据和函数组成。

封装和信息隐蔽

对一个对象进行封装处理可以把他的一部分属性和功能对外屏蔽。封装把对象的内部实现和外部行为分割开来。“封装性”指的是:1.函数讲有关的数据和操作代码封装在一个对象中,形成一个基本单位,各个对象之间相互独立,互不干扰。2.将对象中的某些部分对外隐蔽,也就是隐蔽其内部接口,只留下少量接口和外界联系。有利于数据安全,防止无关的人了解和修改。

抽象

抽象的过程是将事物的共性归纳、集中的过程。抽象的作用是表示同一事物的本质。类是对象的抽象,对象是类的具象。

继承和重用

采用继承的方法可以利用已有的类建立一个新的类,这样可以重用已有软件中的一部分,这就是软件重用。

成员函数的存储方式

同一个类的不同对象的数据(如变量等)会分开存储,但是类中的共同的函数代码段会存放在同一段内存空间中,不占用对向的存储空间,从而大大节约存储空间。而为了多个对象共用的类函数代码能够识别不同的函数代码,C++专门设置了this指针,用来指向不同的对象。

this指针

一个类成员函数中,有时希望引用调用它的对象,对此,C++采用隐含的 this 指针来实现。This 指针是一个系统预定义的特殊指针,指向当前对象,表示当前对象的地址。系统用 this 指针明确指出成员函数当前操作的数据成员所属的对象。实际上,当一个对象调用其成员函数时,编译器先将该对象的地址赋给 this 指针,然后调用成员函数,这样成员函数对对象的数据成员进行操作时,就隐含使用了this 指针。

一般而言,通常不直接使用 this 指针来引用对象成员,但在某些少数情况下,可以使用 this 指针,如重载某些运算符以实现对象的连续赋值等。This 指针不是调用对象的名称,而是指向调用对象的指针的名称。This 的值不能改变,它总是指向当前调用对象。

构造函数

在建立一个对象的时候,提供初始化对象的功能。这是一种特殊的成员函数,不需要用户来调用他,而是在建立对象的时候自动执行。构造函数的名字必须与类名同名,没有类型,不返回任何值,其功能由用户根据初始化的要求自定义。如果用户没有定义构造函数,则C++会自动生成函数体为空的构造函数

  1. 什么时候调用构造函数?在对象进入作用域时调用构造函数,也就是在对象建立的时候调用。

派生类中的构造函数需要完成的工作:

  1. 初始化基类的数据成员
  2. 初始化子对象
  3. 初始化自身的数据成员

多重派生的派生类中的构造函数的构造顺序类似于栈

构造函数的种类:

  1. 默认构造函数
  2. 自定义构造函数
  3. 类型复制构造函数:对象复制可以用一个已有的对象快速复制出多个完全相同的对象,是通过调用复制构造函数实现的。复制构造函数是构造函数的一种,其参数是本类对象,并且采用对象引用的形式。和对象的赋值不同,对象复制是从无到有建立一个新对象,并且使他和一个已有的对象完全相同。
    • 当类内有指针相关变量的时候,需要自定义构造函数,因为默认构造函数采用的值传递会将原对象中指针变量的值直接赋值给新对象,导致两个指针变量指向同一块内存从而使得程序出错,多个类中的指针变量指向同一内存会导致某一对象被销毁的时候,其他对象也会丧失原有的地址空间。
  4. 类型转换构造函数:用于将一个其他类型的数据转换成一个类对象。其结构为类名(指定类型的数据)

析构函数

析构函数是一个特殊的成员函数,它的作用和构造函数相反。当对象生命期结束的时候会自动执行析构函数。其职责是在撤销对象占用的内存之前完成一些清理工作,还可以设计用来执行用户希望在最后一次使用对象之后执行的任何操作。它没有函数类型,没有函数参数,因此不能被重载。如果用户没有声明析构函数,则编译系统会自动生成一个空的析构函数

派生类不能继承基类的析构函数。在执行派生类的析构函数时,系统会自动调用基类的析构函数和子对象的析构函数。

选择题考点:1.若是在函数中定义的一个对象,在函数被调用结束的时候会释放对象,此时析构函数执行 2.static局部对象只有在main函数结束或者调用exit函数的时候才会执行析构并释放。 3.如果是全局对象,则在程序流程离开其作用域时调用该对象的析构函数。 4.如果是用new运算符动态创建对象,则只会在delete运算符时调用析构并释放

静态数据成员

静态数据成员属于各个对象共有的,而不是只属于某个对象的成员,所有对象都可以引用它。而在内存中静态数据成员只占一份空间,因此静态数据成员的值对于所有对象都是一样的。静态数据成员也不随对象建立而分配空间,也不随对象的撤销而释放。它在程序编译时就被分配空间,直到程序结束时才释放。

静态成员函数

静态成员函数不属于某一对象,它和非静态成员函数的根本区别是静态成员函数没有this指针,这也决定了静态成员函数无法访问本类中的 非静态成员。

友元函数和友元类

友元函数是在类内声明的函数,但是它不是本类的成员函数,可以访问本类中的私有成员。

友元类:若B是A的友元类,则B中的所有函数都是A类的友元函数,可以访问A类中的所有成员。通过A类体中声明friend B以实现友元。

友元的关系是单向的,友元的关系也不能传递

面向对象程序设计的一个基本原则是封装性和信息隐蔽。而友元类会破坏封装原则,但是有助于数据共享,能够提高程序效率。因此要在友元能使程序精炼并且大大提高程序效率的时候才使用友元。也就是要在数据共享和信息隐蔽之间选择一个平衡点

重载

使用同一个函数名定义多个函数,这些函数的参数个数和参数类型不同,这就是函数的重载。重载使得一个函数名可以多用,也就是“一名多用”。在重载函数的时候,同名函数的功能应该相同或者相近以提高可读性。

运算符重载

是对于运算符的重载,使得运算符能够在面对不一样的参数时执行不一样的功能。重载运算符能够使得用户程序易于编写,阅读和维护。运算符重载和类结合起来,可以在程序中定义出实用又方便的数据类型。运算符重载使得C++具有更强大的功能,更好地扩充性和适应性

不能重载的运算符:

. 成员访问运算符

.* 成员指针访问运算符

:: 域运算符

?: 条件运算符

双目运算符一般重载为友元函数,而单目运算符多重载为成员函数

类型转换函数

类型转换函数的作用是将一个类的对象转换成为另一类型的数据。类型转换函数只能作为成员函数,因为转换主体是本类对象。函数名前面不能指定函数类型,函数没有参数。编译系统能够识别类中的类型转换函数,从而隐式地调用类型转换函数。

面向对象程序设计

四个主要特点:抽象、封装、继承和多态性

组合
组合是一种聚集关系,是一种部分和整体的关系,也就是一种has-a关系。比如一辆汽车由车体和四个轮子组成,这就是一种组合关系。这是对代码的一种面向对象的封装,负责制造汽车的函数不需要关心制造轮子和车体的函数是如何运作的,他只需要将四个轮子对象和一个车体对象组合起来就好。

继承

继承性是面向对象程序设计最重要的特征,实现了软件的可重用性。通过继承,一个新的子类从父类中获得父类的特性,称为类的继承;从父类中产生新的子类称为类的派生。这是C++和C的重要区别之一。派生类在基类的基础上增加了新的功能,是对基类的具体化和扩展,并且也可以成为未来派生类的基类

使用继承的原因:

  • 许多基类是被程序其他部分或者其他程序所使用的,使用继承可以不改变基类本身的情况下建立新的数据类型。
  • 对事物进行分类,使得事物关系更加清晰。继承提供了is-a关系的描述,继承者是被继承者的进一步细分化
  • 支持软件的增量开发,软件开发并非是一蹴而就的,继承使得在原有软件上添加新功能变得容易。

继承方式有:公有继承、私有继承、保护继承

派生类初始化的顺序:
首先执行基类的构造函数,然后再调用本派生类需要使用的对象成员的构造函数,接着执行本派生类的构造函数。虽然没有显式调用基类的构造函数,但是派生类实例化的时候还是会执行该基类构造函数

派生类的析构函数只会负责回收派生类中新增的数据结构,因此派生类的析构函数会在将新增的数据结构回收后,自动调用基类析构函数,完成整个回收。

运行时多态
由于派生类中已经有一个基类对象,因此派生类可以自动转换为基类对象。将派生类对象赋给基类对象、将基类指针指向派生类、以及定义引用一个派生类对象的基类对象时,都会触发自动转换。

多态
多态性是面向对象程序设计的重要特征。多态使得具有不同功能的函数可以用同一个函数名,从而使得一个函数名调用不同内容的函数。在面向对象方法中,向不同的对象发送同一个消息,不同的对象在接收时可以产生不同的行为,也就是说每个对象可以用自己的方式去响应同样的信息。

多态的实现:
多态分为编译时多态(又称为静态绑定)和运行时多态(又称为动态绑定)。函数重载和通过对象名调用的虚函数,在编译的时候就可以确定其虚函数属于哪个类,因此称为编译时多态。而使用指针去调用虚函数,编译系统无法确定调用哪个类对象的虚函数,因此其关联关系是在运行阶段确定的,所以是运行时多态。

虚基类
C++支持继承多个父类,但是这会出现二义性问题,比如说B和C都继承A类,然后D类继承B类和C类,此时D类中则会含有两个A类的数据结构:一个是继承B类得来的,一个继承C类得来的。虚基类能够使得在继承间接共同基类的时候只保留一份成员。避免出现多个基类数据成员,从而避免导致继承出现二义性。

虚函数
虚函数的作用时允许在派生类中重新定义与基类同名的函数,并且可以通过基类的指针或引用来访问基类和派生类中的同名函数。能够使同一类族中的不同类的对象,对同一函数调用做出不同相应。虚函数是运行时多态的重要实现,在函数头加上virtual关键字标记一个函数为虚函数,该函数的参数、函数名需要和基类虚函数完全一致,否则编译器会以为这是函数重载。

关联
编译系统确定调用的具体对象的过程称为关联,指的是将函数名和一个类对象捆绑在一起,建立关联。而函数重载和通过对象名调用的虚函数,在编译的时候就可以确定其虚函数属于哪个类,因此称为静态关联。而使用指针去调用虚函数,编译系统无法确定调用哪个类对象的虚函数,因此其关联关系是在运行阶段确定的,所以是动态关联。

虚函数表
当类带有虚函数的时候,编译系统会为该类族构造一个虚函数表,是一个指针数组,存放着每个虚函数的入口地址。

虚析构函数
如果对于采用虚函数的基类使用普通的析构函数,会仅仅调用基类的析构函数,而不会调用其派生类的析构函数,这会导致清理不完全。而虚析构函数能够通过动态关联,先调用派生类析构函数,再调用基类析构函数。

纯虚函数
纯虚函数是在基类中定义的一个虚函数,并且仅仅预留一个函数名,没有任何的具体实现,但是要求其派生类需要定义自己的对应的虚函数,这种情况下就可以在基类中声明纯虚函数

抽象类
如果一个类的唯一目的是用它作为基类去建立派生类,不用来定义对象而知识作为一种基本类型用作继承的类,称为抽象类。抽象类是不能实例化的,但是可以声明抽象类的指针变量,然后指向非抽象类的派生类来调用虚函数,实现多态化操作。如果一个基类只要包含了纯虚函数,那这个类就是抽象基类,抽象类的作用是保证派生类都具有基类中包含的纯虚函数个功能。如果一个派生类继承了该抽象类,但是没有实现其中的纯虚函数,那么派生类仍然是抽象类。

泛型机制

类模板
和函数模板一样,可以将不确定的类设计成一个模板,用模板参数代替某些成员函数的类型。定义类模板以template开头,后接形式参数表。

template <模板形式参数表>
class 类名{...}

类模版可以减少重复性工作。类模版包含类形式参数,因此又称为参数化的类,对象是类的实例,而类模版式类的抽象,类是类模版的实例。模板只是一个蓝图,无法直接运行,要运行类模板就必须先指定模板形式参数的值和形式参数的类型,将模板参数和类型代入类模板中形成一个可运行的模板类。

输入输出

C++的输入和输出的种类

包括三种输入和输出:

  1. 对系统指定的标准设备的输入和输出。也就是从键盘输入数据,输出到显示屏幕,这种输入输出称为标准输入输出,C++中使用iostream实现
  2. 以外存磁盘文件作为对象进行输入输出,就是从磁盘文件输入数据,数据输出到磁盘文件,又称为文件的输入输出,C++中使用fstream实现
  3. 对内存指定空间进行输入输出,通常是指定一个字符数组作为存储空间,这种输入输出称之为字符串输入输出,C++中使用sstream实现

C++输入输出流

C++的输入输出流是指若干字节组成的字节序列,这些字节中的数据按照顺序从一个对象传送到另一个对象。流表示了信息从源到目的端的流动。在内存中为每一个数据流开辟了一个数据缓冲区,用来存放流中的数据,当用cout或者<<向显示器输出数据的时候,会先将数据送到输入缓冲区

  • 0
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值