您现在的位置是:首页 >技术交流 >C++,Qt部分面试和笔试题网站首页技术交流
C++,Qt部分面试和笔试题
面试这么多次,C++这块基础太差了,乘着还有印象总结下相关的面试问答和笔试题,后续会不断更新内容
问答题
1.计算机网络七层体系结构
引用:计算机网络七层体系结构
2.C++中关键字static和const的使用
static(静态的)
sataic修饰全局变量:限制全局变量的作用域(使得全局变量只能在本文件中访问)。
static修饰局部变量:延长局部变量的生命周期,(比如子函数中初始化只进行一次,后续调用会跳过初始化,使用上次子函数结束时的值)。
static修饰函数:和修饰全局变量效果相同,都是限制作用域,使得该函数只能在本文将中访问。
const修饰类的成员
const 只读
const int a = 10;
//a的值固定为10,相当于宏定义
const int *p = &a;
//*p的值不能修改,即p指向的空间的内容不能修改,但p的指向可以修改
int * const p = &a;
//p的值不能修改,即p的指向不能修改,但p指向的空间的内容可以修改
const修饰的类对象,只能调用const修饰的成员函数。
const修饰成员函数本质上修饰的是this,这样子参数的类型是与普通成员函数类型不一样的,可以有重载。当发生重载时,const对象会调用const函数,普通对象会调用普通函数
3.QList和QVector for循环输出速度比较
QList的不同数据量遍历都比较慢,耗时超QVector一倍。
QList与QVector遍历方法与性能比较
4.构造函数能否为虚函数
构造函数不能是虚函数。而且不能在构造函数中调用虚函数,因为那样实际执行的是父类的对应函数,因为自己还没有构造好。析构函数可以是虚函数,而且,在一个复杂类结构中,这往往是必须的。
析构函数也可以是纯虚函数,但纯虚析构函数必须有定义体,因为析构函数的调用是在子类中隐含的。
说明:虚函数的动态绑定特性是实现重载的关键技术,动态绑定根据实际的调用情况查询相应类的虚函数表,调用相应的虚函数。
5.谈谈你对面向对象的认识
面向对象可以理解成对待每一个问题,都是首先要确定这个问题由几个部分组成,而每一个部分其实就是一个对象。然后再分别设计这些对象,最后得到整个程序。传统的程序设计多是基于功能的思想来进行考虑和设计的,而面向对象的程序设计则是基于对象的角度来考虑问题。这样做能够使得程序更加的简洁清晰。
说明:编程中接触最多的“面向对象编程技术”仅仅是面向对象技术中的一个组成部分。发挥面向对象技术的优势是一个综合的技术问题,不仅需要面向对象的分析,设计和编程技术,而且需要借助必要的建模和开发工具。
6.Qt信号槽能不能为静态函数
当发送信号的地方为静态函数时,采用上述形式会报错,此时发送信号的类需要添加一个静态指针才能使用。
7.类的初始化顺序
(1)任何虚拟基类(virtual)的构造函数按照它们被继承的顺序构造;
(2)任何非虚拟基类(non-virtual)的构造函数按照它们被继承的顺序构造;
(3)任何成员对象(data member)的构造函数按照它们声明的顺序调用;
(4)类自己的构造函数(self)。
引用: C++构造函数初始化顺序详解
引用 :类的初始化顺序
8.面向对象与面向过程的区别
面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了;面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。
其实就是两句话,面向对象就是高度实物抽象化、面向过程就是自顶向下的编程!
引用 :面向对象 和 面向过程 的区别
9. C++ lambda表达式
例1: // 一般是局部匿名函数 也可以写到全局
auto Add1 = [](int x, int y)->double{return (x + y) / 3.0; };
auto Add2 = [](int x, int y)->int {return-> (x + y) / 3.0; };//
auto Add3 = [a, b] {return (a + b) / 3.0;
};//捕捉变量写法
引用 :C++11:lambda表达式
10.设计模式 -工厂模式
工厂模式可以分为三类: 简单工厂模式(Simple Factory) 工厂方法模式(Factory Method)
抽象工厂模式(Abstract Factory) 简单工厂其实不是一个标准的的设计模式。GOF
23种设计模式中只有「工厂方法模式」与「抽象工厂模式」。简单工厂模式可以看为工厂方法模式的一种特例,为了统一整理学习,就都归为工厂模式。这三种工厂模式在设计模式的分类中都属于创建型模式,三种模式从上到下逐步抽象。
创建型模式 创建型模式(Creational
Pattern)对类的实例化过程进行了抽象,能够将软件模块中对象的创建和对象的使用分离。为了使软件的结构更加清晰,外界对于这些对象只需要知道它们共同的接口,而不清楚其具体的实现细节,使整个系统的设计更加符合单一职责原则。创建型模式在创建什么(What),由谁创建(Who),何时创建(When)等方面都为软件设计者提供了尽可能大的灵活性。
创建型模式隐藏了类的实例的创建细节,通过隐藏对象如何被创建和组合在一起达到使整个系统独立的目的。
工厂模式是创建型模式中比较重要的。工厂模式的主要功能就是帮助我们实例化对象。之所以名字中包含工厂模式四个字,是因为对象的实例化过程是通过工厂实现的,是用工厂代替new操作的。
工厂模式优点:
可以使代码结构清晰,有效地封装变化。在编程中,产品类的实例化有时候是比较复杂和多变的,通过工厂模式,将产品的实例化封装起来,使得调用者根本无需关心产品的实例化过程,只需依赖工厂即可得到自己想要的产品。
对调用者屏蔽具体的产品类。如果使用工厂模式,调用者只关心产品的接口就可以了,至于具体的实现,调用者根本无需关心。即使变更了具体的实现,对调用者来说没有任何影响。
降低耦合度。产品类的实例化通常来说是很复杂的,它需要依赖很多的类,而这些类对于调用者来说根本无需知道,如果使用了工厂方法,我们需要做的仅仅是实例化好产品类,然后交给调用者使用。对调用者来说,产品所依赖的类都是透明的。
适用场景 不管是简单工厂模式,工厂方法模式还是抽象工厂模式,他们具有类似的特性,所以他们的适用场景也是类似的。首先,作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过new就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。
其次,工厂模式是一种典型的解耦模式,迪米特法则在工厂模式中表现的尤为明显。假如调用者自己组装产品需要增加依赖关系时,可以考虑使用工厂模式。将会大大降低对象之间的耦合度。
再次,由于工厂模式是依靠抽象架构的,它把实例化产品的任务交由实现类完成,扩展性比较好。也就是说,当需要系统有比较好的扩展性时,可以考虑工厂模式,不同的产品用不同的实现工厂来组装。
11.qt operator 操作符重载
Point2D &operator +=(const Point2D &other)
{
xVal +=other.xVal();
yVal +=other.yVal();
return *this;
}
引用 :Qt C++ 运算符重载详解
引用 :(十九)QT专题-运算符重载
12.TCP和UDP之间的区别
例1: TCP 面向连接(如打电话要先拨号建立连接)提供可靠的服务,UDP 是无连接的,即发送数据之前不需要建立连接,UDP
尽最大努力交付,即不保证可靠交付。
UDP 具有较好的实时性,工作效率比 TCP 高,适用于对高速传输和实时性有较高的通信或广播通信。
每一条 TCP 连接只能是一对一的,UDP 支持一对一,一对多,多对一和多对多的交互通信。
UDP 分组首部开销小,TCP 首部开销 20 字节,UDP 的首部开销小,只有 8 个字节。
TCP 面向字节流,实际上是 TCP 把数据看成一连串无结构的字节流,UDP 是面向报文的一次交付一个完整的报文,报文不可分割,报文是
UDP 数据报处理的最小单位。
UDP 适合一次性传输较小数据的网络应用,如 DNS,SNMP 等。
13.UDP如何实现可靠传输
一个是重传机制,丢包需要进行重传,可以用ACK也可以用NACK的方式;
第二是重排机制,我们在收到乱序数据一定需要增加一个缓冲区进行数据重排;
第三是超时机制,长时间没收收到对方的回复需要进行重试;
第四,流量控制,在局域网内一般是不考虑这部分,实现起来比较复杂,收益不是那么大。
笔试题
卷一
1.C语言的关键字static 和C++的关键字static有什么区别
例1:
在C中static用来修饰局部静态变量和外部静态变量、函数。在C++中除了上述功能外,还用来定义类的成员变量和函数。即静态成员数据和静态成员函数。
注意:编程时static的记忆性,和全局性的特点可以让在不同时期调用的函数进行通信,传递信息,而C++的静态成员则可以在多个对象实例间进行通信,传递信息。
答案引用:C语言的关键字static和C++的关键字static有什么区别
例2:
首先,C++是C的超集,所以static在C中的用法
对于C++来说是全盘接受的,而两者的不同也就是C++中多出来的特性,而这些多出来的特性与C++面向对象的特性有关,或更具体的说,就是static在“类”中的意义和作用。1:C语言中的Static使用:
1.1 C中static变量 的影响其实不在作用域而在于 其“存储方式”:
即在函数内定义的static变量,其作用域仍然在函数内;在函数外定义的static变量,其作用域也在函数外,属于变量所在的文件的作用域。
static
的静态存储方式使得:同一函数的所有static变量的“副本”都共用一个该变量。所以使用了static变量的函数一般是“不可再入”的,不是“线程安全”的。
1.2 C中static函数 的作用:
C中static函数还有另外一个名字,叫:内部函数。从名字也可看出,C中的static函数的定义将函数“局部化”,使其访问权限被限制在当前文件内部,这实际上说明的是一种“代码的隐藏机制”,通过和extern函数(外部函数)的联合使用,可以实现C语言中函数的模块化设计,这有点类似与C++
中的Public和private关键字的味道。 当然,如果在C中,函数默认的访问权限是extern的,所以关键字extern往往省略不写。
2: C++类中定义的Static变量和函数
其实本质上与C中的情况一致,不在于作用域(还是类的作用域),而在于其“存储方式”决定了Static变量将与类存储在一起(因为类本身在内存中有其原型的内存空间),而类的实例将共享这一static变量,所以static变量也不是“线程安全”的。
而static成员函数的设置,主要是为了访问静态变量,或者完成某些独立于类实例的功能。
答案引用:关键字static在C和C++中的区别
2. c中的malloc个C++的new有什么区别
1、new/delete是C++的操作符,而malloc/free是库函数;
2、new在调用时会先为对象分配内存,再调用对象的构造函数,而malloc不会
3、使用malloc为对象指针分配内存,要明确指定分配内存的大小,而new不需要
4、new作为操作符,可以被重载,而malloc不行
5、new分配内存成功,则返回对象指针;而malloc分配成功会返回void*类型指针
6、new如果分配内存失败会抛出bad_alloc异常;而malloc分配内存失败会返回null指针
7、new从自由存储区为对象分配内存;malloc从堆上分配内存
答案引用:C++ new和malloc的区别
3.一个指针可以是volatil吗
可以。
因为指针和普通变量一样,有事也有变化程序的不可控性。常见例:子中断服务子程序修改一个指向一个buffer的指针时,必须用volatile来修饰指针。指针是一种普通的变量,从访问上没有什么不同于其他变量的特性。其保存的数值是个整形数据,和整型变量不同的是,这个整型数据指向的是一段内存地址。
4.C++的空类有哪些函数
C++的空类会有6个默认的函数。即 默认构造函数、 默认拷贝构造函数、 默认析构函数、
默认赋值运算符,这四个是我们通常知道的。但是除了这四个,还有两个,那就是 取址运算符和 const 取址运算符,即总共有六个函数。
class Empty{
public:
Empty(); // 缺省构造函数
Empty( const Empty& ); // 拷贝构造函数
~Empty(); // 析构函数
Empty& operator=( const Empty& ); // 赋值运算符
Empty* operator&(); // 取址运算符
const Empty* operator&() const; // 取址运算符 const
};
答案引用: C++空类中有哪些默认的函数
5.简述类成员函数的重写、重载和隐藏的区别
(1)重写和重载主要有以下几点不同。
- 范围的区别:被重写的和重写的函数在两个类中,而重载和被重载的函数在同一个类中。
2.参数的区别:被重写函数和重写函数的参数列表一定相同,而被重载函数和重载函数的参数列表一 定不同。
3.virtual的区别:重写的基类中被重写的函数必须要有virtual修饰,而重载函数和被重载函数可以被 virtual修饰,也可以没有。
(2)隐藏和重写、重载有以下几点不同。
1.与重载的范围不同:和重写一样,隐藏函数和被隐藏函数不在同一个类中。
2.参数的区别:隐藏函数和被隐藏的函数的参数列表可以相同,也可不同,但是函数名肯定要相同。
当参数不相同时,无论基类中的参数是否被virtual修饰,基类的函数都是被隐藏,而不是被重写。
说明:虽然重载和覆盖都是实现多态的基础,但是两者实现的技术完全不相同,达到的目的也是完
全不同的,覆盖是动态态绑定的多态,而重载是静态绑定的多态。
答案引用:简述类成员函数的重写、重载和隐藏的区别
6.编码实现直接插入排序
#include <iostream>
#include <vector>
using namespace std;
vector<int> InsertSort(vector<int> list)
{
vector<int>result = list;
if (result.empty()) //判断容器内容是否为空
return result;
//第一个元素是有序的,所以从下标为1的元素开始
for (int i = 1; i < result.size(); i++)
{
int temp = result[i];
int j = i - 1;
//取出第i个元素,将其与之前的元素进行比较,
//直到找到比它小的元素或者遍历完所有元素将其放在开头
for (j; j >= 0 && result[j] > temp; j--)
{
result[j + 1] = result[j];
}
result[j + 1] = temp;
}
return result;
}
int main()
{
int arr[] = { 5, 2, 3, 78, 54, 9, 15, 20 };
vector<int>test(arr, arr + sizeof(arr) / sizeof(arr[0]));
cout << "排序前:" << endl;
for (int i = 0; i < test.size(); i++)
{
cout << test[i] << " ";
}
cout << endl;
vector<int>result = InsertSort(test);
cout << "排序后:" << endl;
for (int j = 0; j < result.size(); j++)
{
cout << result[j] << " ";
}
cout << endl;
system("pause");
}
————————————————
版权声明:本文为CSDN博主「是个可爱的小伙砸」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_38307826/article/details/107334200
答案引用:C++实现排序算法之直接插入排序
7.C++实现在二元树中找出和为某一值的所有路径
8.编码实现某一变量某位清 0 或置 1
给定一个整型变量 a,写两段代码,第一个设置 a 的 bit 3,第二个清 a 的 bit 3,在以上两个操作中,要保持其他位不变。
#define BIT3 (0x1 << 3 ) Satic int a;
//设置a的bit 3:
void set_bit3( void )
{
a |= BIT3; //将a第3位置1
}
//清a的bit 3
void set_bit3( void )
{
a &= ~BIT3; //将a第3位清零
}
卷二
一、请填写BOOL , float, 指针变量 与“零值”比较的 if 语句
整个笔试卷就是这个问档
一、请填写BOOL , float, 指针变量 与“零值”比较的 if 语句