接前面C/C++常见面试题(一),继续巩固
目录
1 sizeof和strlen的区别
2 宏定义的陷进
3 不使用sizeof计算出类型或者变量所占的内存的字节数
4 给定一个数判断是否其是2的N次幂
5 C/C++打印所在文件、行号、函数、日期,时间、遵循的标准
6 简单说一下重载和重写的区别
7 简单讲一下虚函数和纯虚函数
1 sizeof和strlen的区别
回答这个问题从以下三个方面:
a. sizeof是关键字、运算符,而strlen是函数
b. strlen 只能使用char * 做参数,必须以“\0”结尾,一般用于计算字符串的长度,不包括"\0"的所占的空间;sizeof可以用类型或者变量做参数,一般用于计算类型或者变量所占的内存的字节数,因此在计算字符串长度的时候,会包含"\0"所占的内存空间大小。
c. sizeof 是关键字在编译的时候已经计算好了,strlen是在运行程序的时候进行计算的
2 宏定义的陷进
#include <stdio.h>
#define VHU(x) x* x*x
int main()
{
int a = 4;
printf("%d \n",VHU(a+1));
return 0;
}
如上的一个宏定义:
VHU(a+1) = a + 1 * a + 1 * a + 1 = 3*a + 1 = 13
切记宏定义的本质只是简单的替换,因此对于宏定义的操作,一般要求加括号,比如上述的宏定义,要计算x的三次方的话,应该写成 VHU(x) (x)*(x)*(x)
3 不使用sizeof计算出类型或者变量所占的内存的字节数
利用0地址的转换
#define SIZEOF(T) ((size_t)((typeof(T)*)0 + 1))
4 给定一个数判断是否其是2的N次幂
利用与相与得到值为0,可以判断出
仅仅只需要判断 n & (n-1) 是否为0,为0就是2的N次幂,特殊处理一下n <= 0的情况即可
代码如下:
#include <stdio.h>
#include <stdbool.h>bool Is2_n(int n)
{ if (n < 0){printf("输入的值是: %d 不在范围内,应该大于0 Fail Exit\n",n);exit(0);}if (n == 0){return false;}if ((n & (n-1)) == 0){return true;}else{return false;}}int main(int argc,char *argv[])
{if (Is2_n(8)){printf("是2的N次幂\n");}else{printf("不是2的N次幂\n");}return 0;
}
5 C/C++打印所在文件、行号、函数、日期,时间、遵循的标准
ANSIC标准定义了可供C语言使用的预定义宏:
__LINE__ : 在源代码中插入当前源代码行号
__FILE__ : 在源代码中插入当前源代码文件名 __FUNCTION__:在源代码中插入当前源代码所在函数
__DATE__ : 在源代码中插入当前编译日期
__TIME__ : 在源代码中插入当前编译时间 __STDC__:在函数中查看C/C++遵循的标准,ANSI C标准 是一个非0值,一般的C/C++都遵循
ANSI 标准
6 简单说一下重载和重写的区别
回答一:
a. 重载和重写是实现C++多态的两种方式,都可以满足对于不同的对象收到相同的消息产生
不同的行为这一多态特性。重写的实现是利用虚函数实现的。重载是利用相同作用域的
同名函数的不同的参数列表(参数个数、参数类型)实现的。
b. 虚函数是基类希望派生类重新定义的函数,派生类重新定义基类虚函数的做法叫做覆盖
(重写);重载就在允许在相同作用域中存在多个同名的函数,这些函数的参数表不同。
重载的概念不属于面向对象编程,编译器根据函数不同的形参表对同名函数的名称做修
饰,然后这些同名函数就成了不同的函数。
c. 重载的确定是在编译时确定,是静态的,属于编译时多态;虚函数则是在运行时动态确定,
属于运行时多态。
回答二:
重载:
(1)发生在同一个类中;
(2)相同的方法名;
(3)参数列表不同;
(4)不看返回值,如果出现了只有返回值不同的“重载”,是错的;
重写:
(1)发生在子类与父类中;
(2)相同的方法名;
(3)相同的参数列表;
(4)返回值相同 或者 子类方法的返回值是父类方法返回值类型的子类;
(5)访问修饰符相同 或者 子类方法的修饰符范围 大于 父类;
(6)抛出的异常相同 或者 子类方法抛出的异常 小于父类;
方法的重写(Overriding)和重载(Overloading)是多态性的不同表现,重写是父类与子类之间
多 态性的一种表现,重载可以理解成多态的具体表现形式。
方法重载是一个类中定义了多个方法名相同,而他们的参数的数量不同或数量相同而类型和次
序不同,则称为方法的重载(Overloading)。
方法重写是在子类存在方法与父类的方法的名字相同,而且参数的个数与类型一样,返回值也一
样的方法,就称为重写(Overriding)。
方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。
7 简单讲一下虚函数和纯虚函数
虚函数:
在类的成员函数前加virtual关键字。
虚函数是实现多态的基础。一旦基类定义了虚函数,该基类的派生类中的同名函数也自动称
为虚函数。
虚函数的重写:派生类中有一个跟基类的完全相同的虚函数,我们就称子类的虚函数重写了
基类的虚函数。
“完全相同”是指:函数名、参数、返回值都相同。另外,虚函数的重写也叫做虚函数的覆盖。
纯虚函数:
在虚函数的后面写上 = 0,则这个函数为纯虚函数。(纯虚函数没有函数体)
包含纯虚函数的类叫做抽象类(也叫接口类),抽象类不能实例化出对象。派生类继承后也
不能实例化出对象。
只有重写纯虚函数,派生类才能实例化出对象。纯虚函数规范了派生类必须重写,另外纯虚
函数更体现了接口继承。
子类和父类的实例化关系:
子类可以实例化成父类,父类不能实例化成子类,因为子类可能重写了父类,子类的范畴是
大于父类的,大到小是可以的,小到大是不行的。