C++基础知识概念(一)

C++基础知识概念(一)

1 比较值传递和引用传递的相同点和不同点。
值传递是指当发生函数调用时,给形参分配内存空间,并用实参来初始化形参(直接将实参的值传递给形参)。这一过程是参数值的单向传递过程,一旦形参获得了值便与实参脱离关系,此后无论形参发生了怎样的改变,都不会影响到实参。
引用传递将引用作为形参,在执行主调函数中的调用语句时,系统自动用实参来初始化形参。这样形参就成为实参的一个别名,对形参的任何操作也就直接作用于实参。

2 什么叫内联函数?它有哪些特点?
定义时使用关键字 inline 的函数叫做内联函数;内联函数不是在调用时发生控制转移,而是在编译时将函数体嵌入在每一个调用出,节省了参数传递、控制转移等开销;
• 内联函数体内不能有循环语句和 switch 语句;
• 内联函数的定义必须出现在内联函数第一次被调用之前;
• 对内联函数不能进行异常接口声明;
• 定义在类内部的函数是自动内联的。

3 什么叫拷贝构造函数?拷贝构造函数何时被调用?
如果一个构造函数的第一个参数是自身类类型的引用,且任何额外参数都有默认值,则此构造函数是拷贝构造函数其作用是使用一个已经存在的对象(由拷贝构造函数的参数指定),去初始化同类的一个新对象
(1) 当用类的一个对象去初始化该类的另一个对象时;
(2) 如果函数的形参是类的对象,调用函数时将使用实参对象初始化形参对象;
(3) 如果函数的返回值是类的对象,函数执行完成返回主调函数时,将使用return语句中的对象初始化一个临时无名对象,传递给主调函数。
隐含的拷贝构造函数:如果程序员没有为类声明拷贝初始化构造函数,则编译器自己生成一个隐含复制构造函数;该函数执行的功能是:用初始值对象的每个数据成员,初始化将要建立的对象的数据成员。

4 复制构造函数与赋值运算符(=)有何不同?
从概念上区分:复制构造函数是构造函数,而赋值操作符属于操作符重载范畴,它通常是类的成员函数 从原型上来区分
• 复制构造函数原型 ClassType(const ClassType &);无返回值;
• 赋值操作符原型 ClassType& operator=(const ClassType &);返回值为 ClassType 的引用,便于连续赋值操作
从使用的场合来区分:复制构造函数用于产生对象,它用于以下几个地方:函数参数为类的值类型时、函数返回值为类类型时以及初始化语句

5 什么叫作用域?有哪几种类型的作用域?
作用域讨论的是标识符的有效范围,作用域是一个标识符在程序正文中有效的区域。 C++的作用域分为:函数原型作用域、函数作用域、文件作用域(全局作用域)、块作用 域(局部作用域)、类作用域和名字空间作用域。

6 什么叫做可见性?可见性的一般规则是什么?
可见性是标识符是否可以引用的问题; 可见性的一般规则是:标识符要声明在前,引用在后,在同一作用域中,不能声明同名的标识符。对于在不同的作用域声明的标识符,遵循的原则是:若有两个或多个具有包含关系的作用域,外层声明的标识符如果在内层没有声明同名标识符时仍可见,如果内层声明了同名标识符则外层标识符不可见。
比如:在函数中声明的static int a = 2;a为静态局部变量,具有全局寿命,但是只有局部(该函数内)可见,即使离开该函数,其内存空间也不会释放,而下次进入该函数时,也不会重新初始化。

7 什么叫静态数据成员?他有何特点?
类的静态数据成员是类的数据成员的一种特例,采用 static 关键字来声明。对于类的普通数据成员,每一个类的对象都拥有一个拷贝,就是说每一个对象的同名数据成员可以分别存储不同的值,这也是保证对象拥有区别于其他对象的特征的需要,但是静态数据成员,每 个类只有一个拷贝,由所有该类的对象共同维护和使用,这个共同维护,使用也就实现了同一类的不同对象之间的数据共享。

8 什么叫静态函数成员?他有何特点?
使用 static 关键字声明的函数成员是静态的,静态函数成员属于整个类,被同一个类的所有对象共同维护,为这些所有对象共享。
静态成员函数具有以下两个方面的好处
一是由于静态成员函数只能直接访问同一个类的静态数据成员,可以保证不会对该类的其余数据成员造成负面影响;
二是同一个类只维护一个静态函数成员的拷贝,节约了系统的开销,提高程序的运行效率。

9 什么叫友元函数?什么叫友元类?
友元函数是使用关键字 friend 关键字声明的函数,它可以访问相应类的保护成员和私有成员。
在友元函数中用常引用做参数,既能获得较高的执行效率,又能保证实参的安全性。

友元类是使用 friend 关键字声明的类,它的所有成员函数都是相应类的友元函数。
友元不可继承,没有传递性。

10 在函数内部定义的普通局部变量和静态局部变量在功能上有何不同?计算机底层对这两类变量做了怎样的不同处理导致了这种差异?
局部作用域中静态变量的特点是:它并不会随着每次函数调用而产生一个副本,也不会随着函数的返回而失效,定义时未指定初值的基本类型静态变量,会被以 0 值初始化;局部作用域的全部变量诞生于声明点,结束于声明所在的块执行完毕之时,并且不指定初值,意味初值不确定。普通局部变量存放于栈区,超出作用域后,变量被撤销,其所占的内存也被 回收;静态局部变量存放于静态数据存储区,全局可见,但是作用域是局部作用域,超出作用域后变量仍然存在。

11 引用和指针有何区别?何时只能使用指针而不能使用引用?
引用是一个别名,不能为 NULL 值,不能被重新分配;
指针是一个存放地址的变量。
当需要对变量重新赋以另外的地址或赋值为 NULL 时只能使用指针。
引用是一个变量的别名,本身不单独分配自己的内存空间,而指针有自己的内存空间。

12 比较类的 3 种继承方式之间的差别?
• 公有继承,使得基类 public(公有)和 protected(保护)成员的访问属性在派生类中不变, 而基类 private(私有)成员不可访问。
• 私有继承,使得基类 public(公有)和 protected(保护)成员都以 private(私有)成员身份出 现在派生类中,而基类 private(私有)成员不可访问。
• 保护继承中,基类 public(公有)和 protected(保护)成员都以 protected(保护)成员身份出 现在派生类中,而基类 private(私有)成员不可访问。

13 什么叫虚基类?有何作用?
当某类的部分或全部直接基类是从另一个基类派生而来,这些直接基类中,从上一级基类继承来的成员就拥有相同的名称,派生类的对象的这些同名成员在内存中同时拥有多 个拷贝,我们可以使用作用域分辨符来唯一标识并分别访问它们。
我们也可以将直接基类的共同基类设置为虚基类,这时从不同的路径继承过来的该类成员在内存中只拥有一个拷 贝,这样就解决了同名成员的唯一标识问题。
虚基类的声明是在派生类的定义过程,其语法格式为: class 派生类名:virtual 继承方式 基类名 上述语句声明基类为派生类的虚基类,在多继承情况下,虚基类关键字的作用范围和 继承方式关键字相同,只对紧跟其后的基类起作用。
声明了虚基类之后,虚基类的成员在 进一步派生过程中,和派生类一起维护一个内存数据拷贝。 虚基类就是为了解决多继承产生的二义性问题

14 组合与继承有什么共同点和差异?通过组合生成的类与被组合的类之间的逻辑关系是什 么?继承呢?
组合和继承它们都使得已有对象成为新对象的一部分,从而达到代码复用的目的。组合 和继承其实反映了两种不同的对象关系。
组合反映的是“有一个”(has-s)的关系,如果类 B 中存在一个类 A 的内嵌对象,表示的 是每一个 B 类型的对象都“有一个”A 类型的对象,A 类型的对象与 B 类型的对象是部分整体 的关系。
继承反映的是“是一个”(is-a)的关系,在“是一个”关系中,如果类 A 是类 B 的公有基 类,那么这表示每一个 B 类型的对象都“是一个”A 类型的对象,B 类型的对象与 A 类型的对 象是特殊与一般的关系。

15 基类与派生类的对象,指针或引用之间,哪些情况下可以隐含转换,哪些情况下可以显 示转换?在涉及多重继承或虚继承的情况下,在转换时会面临哪些新问题?
派生类指针可以隐含转换为基类指针,而基类指针要想转换为派生类指针,则转换一定 要显示地进行。因为从特殊的指针转换到一般的指针是安全的,因此允许隐含转换;
从一般的指针转换到特殊的指针是不安全的,因此只能显示地转换。基类对象一般无法被显式转换为派生类对象。
在多重继承情况下,执行基类指针到派生类指针的显式转换时,有时需要将指针所存储的地址值进行调整后才能得到新指针的值。
但是,如果 A 类型是 B 类型的虚拟基类,虽然 B 类型的指针可以隐含转换为 A 类型,但是 A 类型指针却无法通过 static_case 隐含转换为 B 类型的指针。

16 什么叫做多态性?在 C++种是如何实现多态的?
多态是指同样的消息被不同类型的对象接收时导致完全不同的行为,是对类的特定成员函数的再抽象。C++支持重载多态、强制多态、包含多态和参数多态。 在基类中声明相应的函数为 virtual 型,然后在派生类中实现该函数,这样就可以通过 基类指针调用派生类对象的函数,实现了运行时动态绑定,即多态的功能。
多态性提高了软件的可扩展性,调用多态行为的软件可以用于接收消息的对象类型无关的方式编写。因此,不用修改基本系统,就可以把能够响应现有消息的新类型的对象添加到系统中。只有实例化新对象的客户代码必须修改,以适应新类型。

17 什么叫抽象类?抽象类有何作用?抽象类的派生类是否一定要给出纯虚函数的实现?
带有纯虚函数的类是抽象类。其主要作用是通过它为一个类族建立一个公共的接口,使他们能够更有效地发挥多态特性。抽象类声明了一个类族派生类的共同接口,而接口的完整实现,即纯虚函数的函数体,要由派生类自己定义。抽象类派生出新的类之后,如果派生类 给出所有纯虚函数的函数实现,这个派生类就可以定义自己的对象,因而不再是抽象类;反之,如果派生类没有给出全部纯虚函数的实现,此时的派生类仍然是一个抽象类。

18 在 C++中,能否声明虚构造函数?为什么?能否声明虚析构函数?有何用途?
在 C++中,不能声明虚构造函数,多态是不同的对象对同一消息有不同的行为特性,虚函数作为运行过程中多态的基础,主要是针对对象的,而构造函数是在对象产生之前运行的, 因此虚构造函数是没有意义的;
可以声明虚析构函数,析构函数的功能是在该类对象消亡之前进行一些必要的清理工作, 如果一个类的析构函数是虚函数,那么,由它派生而来的所有子类的析构函数也是虚函数。 析构函数设置为虚函数之后,在使用指针引用时可以动态联编,实现运行时的多态,保证使 用基类的指针就能够调用适当的析构函数针对不同的对象进行清理工作。

19 什么叫做流?流的提取和插入是指什么?I/O 流在 C++中起着怎样的作用?
流是一种抽象,它 负责在数据的生产者和数据的消费者之间建立联系,并管理数据的流 动,一般意义下的读操作在流数据抽象中被称为(从流中)提取,写操作被称为(向流中) 插入。
操作系统是将键盘、屏幕、打印机和通信端口作为扩充文件来处理的,I/O 流类就是 用来与这些扩充文件进行交互,实现数据的输入与输出。

20 什么叫做异常?什么叫做异常处理?
• 异常是一种处理错误的方式,当一个函数发现自己无法处理的错误时就可以抛出异常,让函数的直接或间接的调用者处理这个错误。
• 程序运行中有些错误是可以预料但不可避免的,当出现错误时,要力争做到允许用户排除环境错误,继续运行程序,这就是异常处理程序的任务。
• C++异常处理的任务,不仅在于它能够处理不同类型的异常,还在于它具有在栈解旋期间为异常抛出前构造的所有局部对象自动调用析构函数的能力。

21 C++的异常处理机制有何优点?
C++的异常处理机制使得异常的引发和处理不必在同一函数中,这样底层的函数可以着 重解决具体问题,而不必过多地考虑对异常的处理。上层调用者可以在适当的位置设计对不同类型异常的处理。

22 比较函数重载和虚函数在概念和使用方式方面有什么区别?
函数重载可以用于普通函数(非成员的函数)和类的成员函数,而虚函数只能用于类的成员函数
函数重载可以用于构造函数,而虚函数不能用于构造函数。
如果对成员函数进行重载,则重载的函数与被重载的函数应当都是同一类中的成员 函数,不能分属于两个不同继承层次的类。函数重载是横向的重载。虚函数是对同 一类族中的基类和派生类的同名函数的处理,即允许在派生类中对基类的成员函数 重新定义。虚函数的作用是处理纵向的同名函数。
重载的函数必须具有相同的函数名,但函数的参数个数和参数类型二者中至少有一 样不同,否则在编译时无法区分它们。而虚函数则要求再同一类族中的所有虚函数 不仅函数名相同,而且要求函数类型、函数的参数个数和参数类型都全部相同,否 则就不是重定义了。也就不是虚函数了。
函数重载是在程序编译阶段确定操作的对象的,属静态关联。虚函数是在程序运行 阶段确定操作的对象的,属动态关联。

23 比较 class 和 struct 结构体的异同
不同之处:
默认成员访问权限不同,struct 默认是 public,而 class 默认是 private。
默认继承方式不同,struct 默认是 public,而 class 默认是 private。
在定义模板参数时可以用 class 但不能用 struct。 相同之处在于:都可以包含成员函数,都可以实现继承,都可以实现多态。

24 浅拷贝和深拷贝的区别?
在某些情况下,类内的成员变量需要动态开辟堆内存,如果实行按位拷贝,就可能会出 现两个对象里面的成员变量指针指向同一块内存区域。当回收其中一个对象时,该对象成员 变量所指向的内存区域也将回收,会导致另一个对象存在野指针的情况。非常危险。 深拷贝和浅拷贝可以简单理解为:如果一个类拥有资源,当这个类的对象发生复制过程 的时候,资源重新分配,这个过程就是深拷贝,反之,没有重新分配资源,就是浅拷贝。

25 const 和 static 作用 const 作用:
const:
定义 const 常量,具有不可变性,保护被修饰的东西。防止意外修改,增强程序的 健壮性。
便于类型检查,使编译器对处理内容有更多的了解。
可以避免意义模糊的数字出现,也便于进行参数的修改。同宏定义一样,可以做到 不变则以,一变都变。
const 定义的常量在程序运行过程中只有一份拷贝,而宏定义却又若干份拷贝。
static:
作为类的静态数据成员:被类的所有对象共同拥有,在内存中只有一份拷贝。在类 内声明,在类外初始化。
在全局变量前加上 static 关键字,该变量被定义为一个全局变量,
特点:
a) 变量在全局数据区分配内存
b) 如果不显示初始化,则隐式的初始化为 0
c) 作用域仅限于本文件内
在局部变量前加 static 关键字,该变量被定义为静态局部变量,
特点:
a) 在全局数据区分配内存
b) 如果不显示初始化,则隐式的初始化为 0
c) 始终驻留在全局数据区,直到程序结束。作用域仅限于函数体内,当函数执行 完后作用域随之消失。
静态函数,
特点:
a) 静态函数只能在本源文件中使用
b) 在文件作用域下声明的 inline 函数默认是 static 的

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值