c++/c面试题学习汇总

1. 多态的实现原理?

原理:多态”的关键在于通过基类指针或引用调用一个虚函数时,编译时不确定到底调用的是基类还是派生类的函数,运行时才确定,让程序拥有了多个运行状态。
多态又分为 编译时多态和运行时多态。
编译时多态:比如重载
运行时多态:比如重写

2. 成员模板函数不能为虚函数,同时也不能有默认参数

编译器在编译一个类的时候,需要确定这个类的虚函数表的大小。一般来说,如果一个类有N个虚函数,它的虚函数表的大小就是N,如果按字节算的话那么就是4*N。如果允许一个成员模板函数为虚函数的话,因为我们可以为该成员模板函数实例化出很多不同的版本,也就是可以实例化出很多不同版本的虚函数,那么编译器为了确定类的虚函数表的大小,就必须要知道我们一共为该成员模板函数实例化了多少个不同版本的虚函数。显然编译器需要查找所有的代码文件,才能够知道到底有几个虚函数,这对于多文件的项目来说,代价是非常高的,所以才规定成员模板函数不能够为虚函数。

3. 虚函数表

每一个有虚函数的类(或有虚函数的类的派生类)都有一个虚函数表,该类的任何对象中都放着该虚函数表的指针。
虚函数表是编译器生成的,程序运行时被载入内存。一个类的虚函数表中列出了该类的全部虚函数地址。

4. 静态static成员函数不能成为virtual虚函数

5.指针常量和常量指针

const int* p;     // 01:指针常量,指向的内容是常量,无法通过指针p修改指向的值
int const* p;        // 02:同上,不同的写法
int * const p;          // 03:常量指针,该指针是常量,必须初始化,且初始化后不能修改其指向的地址
const int * const p;    // 04:指向常量的常量指针
int const * const p;    // 05:同上,不同的写法

6.迭代器什么时候失效?

(1)对于list中只有元素的删除操作会导致指向该元素的迭代器失效,其他元素迭代器不受影响
(2)对于vector元素的删除、插入操作会导致指向该元素以及后面的元素的迭代器失效
(3)当插入(push_back)一个元素后,end操作返回的迭代器肯定失效
(4)当插入(push_back)一个元素后,capacity返回值与没有插入元素之前相比有改变,则需要重新加载整个容器,此时first和end操作返回的迭代器都会失效。不增容不会导致迭代器失效。
(5)当进行删除操作(erase,pop_back)后,指向删除点的迭代器全部失效;指向删除点后面的元素的迭代器也将全部失效。

7.二维数组按照行遍历效率高,还是按列遍历效率高?

按行遍历快,首先内存存储数据是按一行一行存储数据的,按行遍历时可以由指向数组第一个数的指针一直往下走,就可以遍历完整个数组,而按列遍历则要获得指向每一列的第一行的元素的指针,然后每次将指针指下一行,但是指针的寻址很快,所以不会有明显的区别。
物理内存是以页的方式进行划分的,当一个二维数组很大是如 int[128][1024],假设一页的内存为4096个字节,而每一行正好占据内存的一页,如果以列的形式进行遍历,就会发生128*1024次的页面调度,而如果以行遍历则只有128次页面调度,而页面调度是有时间消耗的,因而调度次数越多,遍历的时间就越长。

8.函数重载的时候参数列表相同怎么解决同名冲突?

C语言没有办法,所以要熟知系统函数名,尽量不要冲突; C++等其他面向对象的语言可以通过命名空间在一定程度上解决这个问题,但命名空间也不能重名(可以嵌套)。

9.字符常量,字符串常量,合法的字符串常量

//C语言里面字符串,与字符表示
char a[]="aa"; //双引号为字符串常量
char *p="asdf"; //两种存储方式,一种是字符数组,一种是字符指针
char b='a';  //单引号为字符常量 范围-128-127 只能有一个字符
//c++中
char* as = "adcs"; //错误
string aa = "sjdsiqow"; //正确
char a[3] =  "aa" ;    //正确
char a[2] =  "aa" ;     //错误


10.运算符重载

只能通过成员函数重载的运算符有:

= 赋值运算符,()函数调用运算符,[ ]下标运算符,->通过指针访问类成员的运算符,?:条件运算符

不能进行重载的运算符:成员运算符,作用域运算符,条件运算符,sizeof运算符,typeid(一个RTTI运算符),const_cast、dynamic_cast、reinterpret_cast、static_cast强制类型转换运算符

11.c++ 类中默认函数与变量是private类型

12.switch表达式

switch后面括号中表达式可以int、char、枚举类型中的一种,不能是float类型,case 后面必须是常量表达式,表达式中不能包含变量。

13.二维数组作为参数传参

函数形参可以为
类型名 (*s) [列数]
类型名 S[ ] [列数] 可以省略列数

14.重载、重写、重定义

(1) 函数重载,运算符重载是指在相同作用域内,函数名相同,参数列表不同,返回值可相同,可不同。
(2)重写是指子类覆盖父类的方法,参数列表相同,返回值相同
(3)重定义是指派生类中重新定义了基类中某个函数,这将会隐藏掉基类中的函数,列表可相同可不同,相同时只有基类是非虚函数才会被隐藏,不同的时候基类函数是不是虚函数都会被隐藏。

15.静态成员与非静态成员

静态成员存于内存中,非静态成员需要实例化后才会分配内存,所以静态成员不能访问非静态成员,而非静态成员可以直接访问类中静态的成员。

16.函数重载不以返回值类型作为区别

17.C++中一个类的大小

c++标准规定一个类的大小不为0,空类的大小为1,当类中不包含虚函数和非静态数据成员时,其对象大小也为1。虚函数、成员函数(包括静态和非静态)、静态成员都是不占用对象的存储空间的。
类大小=虚函数指针+所有非静态数据成员大小+因字节对齐而多占的字节

18.定义在class中的成员函数默认是inline函数

19.构造函数是保护类型时,该类无法实例化,只能继承。

20.内联函数

递归函数不能定义为内联函数,内联函数一般适合不存在while和switch等复杂的结构且只有1~5条语句的小函数上,否则编译系统将该函数视为普通函数。

21.析构函数

(1)一个类有且只有一个析构函数
(2)析构函数的名字与类名相同,前面加~
(3)析构函数没有参数和返回值
(4)析构函数可以定义在类内,也可以在类外

22.友元函数

友元函数是不能被继承的,友元函数没有this指针。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值