C++面试题目整理(三)

1 结构体 sizeof 内存对齐作用

1 字节对齐不仅便于CPU的快速访问,使CPU性能达到最佳 ,且节省空间
2 pragmatic pack(n) 按照n个字节对齐

2 (1.4指针)

  1  指针是一个变量,本身独立 无论是 指向还是本身内容都可以改变 .
  2 引用本身不具有逻辑独立性质,需要依赖

3 野指针 空指针

1 创立时指针不会指向NULL ,应该指向NULL 或者合理值
如果不指向则会造成野指针
2 当指针被 free 或者 delete 时 没有指向 null 也会造成野指针
3 指针操作超越了变量的范围 , 比如 返回栈内存指针 ,会造成野指针.

4 #define 有那些缺陷

1 无法进行类型检查,只是进行简单的文本替换
2 由于优先级不同,可能会引起错误
3 函数调用实在程序运行时产生的它需要 临时分配内存单元有参数传递和压栈和出站的操作.
4 宏定义替换发生在编译期间

5 判断变量是2有符号数还是无符数
正数以0 开头 ,负数以1 开头 
1 对某个数取反操作,如果 本身和取反后都大于0 ,则判断为有符号数.
2 无符号数则不会受影响
 (a>=0)&&(~a>=0)则判定为有符号数
5 inline 宏定义

1 内联函数 :代码被插入到调用着代码处
2宏定义是在预处理时进行替换,
3inline 是在编译阶段进行展开

6 C 中 struct 和 union 有什么区别
1 在C中只是结构体 
  union  共享内存 按照最大字节分配内存地址  
  值按照最后一次的存储
 2 struct 按照 变量来分配
7C和C++ 中
1 C中struct只是一个结构是变量的集合体
2 没有成员函数,没有权限之说
3  在C++ 中 如果没有多态和虚继承 struct 和class 完全等等同  有三点不同
  (1)  继承权限 struct 默认 public 继承 class 默认 private 继承
  (2)  数据访问权限  struct  默认是public 权限 class 默认 private  
  (3) calss  还用于模板类 
 为什么还要保存struct  
     一是为了兼容C, 二是class 是一个实体(实体有数据和操作) ,如果仅仅是为了数据结构 一般用struct 比较好.
8 float 和double 由于舍入误差 不能直接使用 == != 与如任何数字比较 应该转化成为 >= 或者 < = 一个范围值

1 对于浮点数可以这样和0 比较是否相等

float x; 
    // 正确方式
	const float EPSINPON = 0.00001;
	if((x>=EPSINPON)&&(x<=EPSINPON)) 
	
	if(x==0) //是错误的 判断方式
9 二进制1的个数
获取 最后二进制最后一个  运算
 n&(-n)    eg:   n=010100    -n= 101100        n&(-n) = 000100;
 去掉n进制中的最后一个 1   n&(n-1)
 负数反码  : 除了符号位外 按照位数取反 
 补码 :  正数 原反码补码 相同 
负数的补码 等于 反码 +1 
#include <stdio.h>
int  func(unsigned int x)
{
	int cnt = 0;
	while (x)
	{
		//if (n & 1) {
		//	cnt++;
		//}
		cnt++;
		x = x & (x - 1);
	}
	return cnt;
}
10 大小端

1 小端 低地址存放低字节
在这里插入图片描述
2 大端
低地址存放搞字节
如何验证大小端 通过联合体(联合体都是从低地址开始存放的 )

int  check(void)
{
	union test {
		int a;
		char b;
	 } c;
	c.a = 1;
	return (c.b == 1);    // intel  上输出 1  小端模式
}

11 函数重载与覆盖隐藏

1  重载  : 在同一个可访问作用域内声明几个具有不同参数列表的同名函数  ,在编译期间就确定了是静态,函数地址已经绑定了 ,与多态无关. 重载不关心函数参数返回值,因此不能通过返回值进行重载 
 关键点 : 同一个类中
               函数名字相同
               参数列表不同
               virture 关键字可有可无
   eg : double fun(double) 
           int fun(double) 
           不是重载

2 覆盖是指派生类中存在重新定义基类的函数,其函数名 参数列表 返回值类型 必须与被覆盖函数严格一致 . 当子类 对象调用同名函数时 会自动调用子类中覆盖的版本,它和真正的多态相关
覆盖特征
1 不同的范围(分别位于基类和派生类)
2 函数名字 参数列表 相同
3 基类函数必须有virtual
重载和覆盖区别
覆盖是 子类和基类之间的关系,是垂直关系 .重载是同一个类中函数之间的关系
覆盖是运行时确定的,重载是编译时确定的
覆盖中 调用那函数是根据对象(对象类型 )的类型决定的
隐藏: 派生类的函数屏蔽了同名的基类函数
规则 (1) : 派生类函数与基类函数同名,但是参数不同,无论有无virtual关键字,基类的函数都将在子类被隐藏
(2) 如果派生类的函数与基类的函数同名,并且参数也同名,virtual ,基类函数都会被隐藏.

code 代码验证

class  Base {
public: 
	virtual  void f(float x) {
		cout << " Base :: f(float)" << x << endl;
	}
	void g(float x) {
		cout << " Base :: g(float)" << x << endl;
	}
	void h(float x) {
		cout << " Base :: h(float)" << x << endl;
	}
};

class Derived :public Base
{
	public:
	virtual  void f(float x) {
		cout << " Derived :: f(float)" << x << endl;
	}
	void g(int x) {
		cout << " Derived :: g(int )" << x << endl;
	}
	void h(float x) {
		cout << " Derived :: h(float)" << x << endl;
	}
};

int main()
{
	
	Derived d;
	Base* par = &d;
	Derived* son = &d;
	
	par->f(3.14);  // 子类 动态绑定为子类
	par->g(3.14);  // 父类
	par->g(3);     // 父类
	par->h(3.14);  //父类 
	son->f(3.14);  //子类  参数不同在子类中被隐藏
	son->g(3.14);  //子类  输出3 
	son->h(3.14);  //子类   参数相同在子类中被隐藏 不是叫做覆盖
	//cout << check();
	return 0;
}

在这里插入图片描述

#### 12 数组指向验证


	int a[5] = {1,2,3,4,5};   // a 有两个意思 
	                          //  (1) 数组元素首地址 
	                          //  (2) a表示大小为5 int 的数组
	printf("\n");
	printf("%p", (a+1));      // 这里a表示首地址
	printf("\n");

	int* ptr = (int*)(&a + 1);  //  &a 是一个指向 int(*)[5] 的指针 +1 
	                            //  直接移动到末端 &a+1=&a+sizeof( int(*)[5]= &a+20 
	                            //   a向后移动了5个单位指向 a[5] , ptr 指向a[5]
	                            // ptr 是int*  所以-1 就指向 a[4];
	cout << *(ptr - 1) << endl;   
	cout << sizeof(a) << endl;
	cout << sizeof(&a);
	
	//cout << check();
	return 0;

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值