首页 > 编程语言 >c++ 面试整理

c++ 面试整理

时间:2023-08-19 16:48:23浏览次数:27  
标签:类型 函数 编译 派生类 c++ 面试 内存 基类 整理

如何理解封装、继承、多态
封装
可以隐藏实现细节,使得代码模块化;封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。

多态
多态指同一个实体同时具有多种形式。在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数。如果对象类型是派生类,就调用派生类的函数;如果对象类型是基类,就调用基类的函数
C++中,实现多态有以下方法:虚函数,抽象类,覆盖,模板,条件是要有重写,要有继承,父类指向子类。

继承
继承可以使得子类具有父类的各种属性和方法,而不需要再次编写相同的代码。在令子类别继承父类别的同时,可以重新定义某些属性,并重写某些方法,即覆盖父类别的原有属性和方法,使其获得与父类别不同的功能。另外,为子类别追加新的属性和方法也是常见的做法。

虚函数的作用及其实现原理

虚函数实现原理:
** 虚函数表:**
含有虚函数的类包含用于虚函数表。
特别:

  • 虚函数表是在编译时创建
  • 虚指针是在定义对象时生成,并指向虚函数表
    
  • 虚指针位于对象存储的最前方
    


构造函数能不能是虚函数
不能

a.构造一个对象时,必须知道对象实际类型,而虚函数是在运行期间确定实际类型的。而在构造一个对象时,由于对象还未构造成功,编译器就无法知道对象的实际类型,是该类本身,还是派生类,还是其他。
b.虚函数的执行依赖于虚函数表,而虚函数表是在构造函数中进行初始化的,即初始化虚表指针(vptr),使得正确指向虚函数表。而在构造对象期间,虚函数表(vtable)还没有被初始化,将无法进行。

C++中Overload、Overwrite及Override的区别
Overload(重载):在C++程序中,可以将语义、功能相似的几个函数用同一个名字表示,但参数或返回值不同(包括类型、顺序不同),即函数重载。
(1)相同的范围(在同一个类中);
(2)函数名字相同;
(3)参数不同;
(4)virtual 关键字可有可无。

Override(覆盖):是指派生类函数覆盖基类函数,特征是:
(1)不同的范围(分别位于派生类与基类);
(2)函数名字相同;
(3)参数相同;
(4)基类函数必须有virtual 关键字。

Overwrite(重写):是指派生类的函数屏蔽了与其同名的基类函数,规则如下:
(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。
(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)。

宏函数和inline函数的异同点

  • 内联函数在编译时展开,而宏在预编译时展开
  • 在编译的时候,内联函数直接被嵌入到目标代码中去,而宏只是一个简单的文本替换。
  • 内联函数可以进行诸如类型安全检查、语句是否正确等编译功能,宏不具有这样的功能。

define 和 typedef 区别
(1)原理不同
define是C语言中定义的语法,是预处理指令,在预处理时进行简单而机械的字符串替换,不作正确性检查,只有在编译已被展开的源程序时才会发现可能的错误并报错。
typedef是关键字,在编译时处理,有类型检查功能。它在自己的作用域内给一个已经存在的类型一个别名,但不能在一个函数定义里面使用typedef。

(2)功能不同
typedef用来定义类型的别名,起到类型易于记忆的功能。
define不只是可以为类型取别名,还可以定义常量、变量、编译开关等。

(3)作用域不同
define没有作用域的限制,只要是之前预定义过的宏,在以后的程序中都可以使用,而typedef有自己的作用域。

C++的内存管理机制

  1. 栈: 在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。  
  2. 堆:就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。  
  3. 自由存储区:就是那些由 malloc等分配的内存块,他和堆是十分相似的,不过它是用free来结束自己的生命的。  
  4. 全局/静态存储区:全局变量和静态变量被分配到同一块内存中,在以前的C语言中,全局变量又分为初始化的和未初始化的,在C++里面没有这个区分了,他们共同占用同一块内存区。
  5. 常量存储区: 他们里面存放的是常量,不允许修改。

C语言中的malloc/free和C++中的new/delete的区别和联系
区别1:类型
malloc/free是函数,而new/delete是关键字、操作符

区别2:作用
malloc/free只是简单的进行内存的申请和释放;new/delete除了进行内存申请和释放,还会调用对象的构造函数和析构函数进行空间的初始化和清理

区别3:参数与返回值
malloc/free需要手动计算申请内存的空间大小,而且返回值是void*,需要自己转换成所需要的类型;
new/delete可以自己计算类型的大小,返回为对应的类型指针

c++关键字mutable作用


class Car
{
public:
    Car();
    ~Car();
    int getPrice() const; /*调用方法  const成员函数*/
    int getLen() const; /*调用方法 const成员函数*/
private:
    int m_carPrice;
    int m_carLen;
    mutable int m_carNum;            
};
Car::Car()
{
    m_carPrice = 50000;
    m_carLen = 5;
    m_carNum = 5;
}
Car::~Car()
{
}
int Car::getPrice() const
{
    m_carNum++;    //此处修改是可以,因为对m_carNum进行了mutable限定
    std::cout << m_carPrice  << std::endl;
    return m_carPrice ; // 无法修改该成员变量
}
int Car::getLen() const
{
    return m_carLen; // 无法修改该成员变量
}

在某些场合我们还是需要在const成员函数中修改成员变量的值,被修改的成员变量与类本身并无多大关系,也许你会说,去掉函数的const关键字就行了。 可问题是,我只想修改某个变量的值,其他变量希望仍然被const关键字保护。 这样做相当于在函数中给mutable变量开了特例。

预编译在做些什么事情?
预编译又称为预处理,是做些代码文本的替换工作。主要处理#开头的指令,比如拷贝#include包含的文件代码,#define宏定义的替换,条件编译等。就是为编译做预备工作的阶段。

堆和栈的区别,以及为什么栈效率高
堆是由低地址向高地址扩展;栈是由高地址向低地址扩展。
堆中的内存需要手动申请和手动释放;栈中内存是由OS自动申请和自动释放,存放着参数、局部变量等内存。
堆中频繁调用malloc和free,会产生内存碎片,降低程序效率;而栈由于其先进后出的特性,不会产生内存碎片。
堆的分配效率较低,而栈的分配效率较高。

栈的效率高的原因:
栈是操作系统提供的数据结构,计算机底层对栈提供了一系列支持:分配专门的寄存器存储栈的地址,压栈和入栈有专门的指令执行;而堆是由C/C++函数库提供的,机制复杂,需要一些列分配内存、合并内存和释放内存的算法,因此效率较低。

标签:类型,函数,编译,派生类,c++,面试,内存,基类,整理
From: https://www.cnblogs.com/ultramanX/p/17642632.html

相关文章

  • 二分搜索法-C++
    二分法,就是对一个数组中,已经排好序的数字进行搜索。使用二分法的前提条件:1.是一个数组2.该数组中的数字已经是有序的,比如升序的数字或者降序的数字都可以。inta[]={1,2,3,4};   intb[]={4,3,2,1};3.该数组中没有出现重复的数字 二分法原理:就是对一个数组,不断的划分......
  • C++问题汇总
    一、执行C++程序报错1、现象#现象./gtest_W:/lib64/libstdc++.so.6:version`GLIBCXX_3.4.20'notfound(requiredby./gtest_W)./gtest_W:/lib64/libstdc++.so.6:version`CXXABI_1.3.9'notfound(requiredby./gtest_W)./gtest_W:/lib64/libstdc++.so.6:version......
  • C++入门到放弃(11)——继承
    ​继承是面向对象编程语言当中,最重要的部分,也是代码重用的一种重要形式。不知道为啥不能添加代码了,全部只能用图片替代了。1.基本形式首先继承的有三种基本形式,分别是public、private、protected,代表公有继承、私有继承和保护继承,之前在介绍作用范围的时候提过这三者的区别,但这......
  • VScode软件的安装以及C/C++环境配置的方法
    今天和大家分享一下VScode软件的安装以及C/C++环境配置的方法。手把手教大家入门。1,下载VScode编译器(1)   官网下载链接:https://code.visualstudio.com/ (2)安装VScode。安装过程中的附加任务建议全部勾选。 至此VScode安装完成 2,下载编译器MinGW。(1)下载地址:https:......
  • c++ 多线程
    #include<iostream>#include<functional>#include<thread>#include<future>//std::promise,std::future#include<chrono>voidprint_int(std::future<int>&fut){intx=fut.get();......
  • 如何在C++程序中借助Windows自带的bitsadmin命令从123云盘(不开通直链或会员)上下载文件
    最近,我想发布一个程序,里面想嵌入一些比较大的文件,但是如果直接用资源方式嵌入的话程序的体积就非常大,所以我想用从网上下载的方式获取这些文件。之前我试过很多方式,都没有成功,最后找到了这种方式...准备工作:先了解一下bitsadmin命令的语法,详见官方文档https://learn.microsof......
  • python 面试题第一弹
    1.如何理解Python中的深浅拷贝浅拷贝(ShallowCopy)创建一个新的对象,该对象的内容是原始对象的引用。这意味着新对象与原始对象共享相同的内存地址,因此对于可变对象来说,如果修改了其中一个对象,另一个对象也会受到影响。浅拷贝通常使用copy模块的copy()函数或者对象的copy()方法来......
  • c++[1]
    命名空间:为什么要使用命名空间?使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,于是就有了关键字namespace举个例子:#include<iostream>#include<stdlib.h>//头文件中包含rand函数的定义intrand=10;//命名冲突intmain(){ printf("%d",rand);......
  • C++中String的语法及常用接口用法
    在C语言中,string是一个标准库类(class),用于处理字符串,它提供了一种更高级、更便捷的字符串操作方式,string 类提供了一系列成员函数和重载运算符,以便于对字符串进行操作和处理。一、string类在学习string前,我们不妨先来了解一下string类到底是什么,有什么用呢?我们先来了解一下基本......
  • C++项目实战之演讲比赛流程管理系统
    演讲比赛流程管理系统1.演讲比赛程序需求1.1比赛规则学校举行一场演讲比赛,共有12个人参加。比赛共两轮,第一轮为淘汰赛,第二轮为决赛每名选手都有对应的编号,如10001~10012比赛方式:分组比赛,每组6个人第一轮分为两个小组,整体按照选手编号进行抽签后顺序演讲10个......