2019备战招聘--C++面试(一)

c++知识点总结
  • 本来是精通java基础知识的,迫于社会压力转战C++!门槛高一点!希望大家都能拿到offer!
1.虚函数与纯虚函数的比较
  • 虚函数是为了重载和多态的需要,在基类中是有定义的,即便定义是空,所以子类中可以重写也可以不写基类中的此函数。
  • 纯虚函数在基类中是没有定义的,必须在子类中加以实现。
  • 虚拟函数就是为了对“如果你以一个基础类指针指向一个衍生类对象,那么通过该指针,你只能访问基础类定义的成员函数”这条规则反其道而行之的设计。
  • 多态的真正体现就是基类指针访问子类对象。
  • 虚函数动态联编,虚函数表。
  • 在函数编译过程中,父类子类中的成员函数的名字是不一样的,可以区分,然后函数如果调用成员变量,函数会默认传进去一个该类的指针,进行调用。
2. 重载、重写、隐藏区别
  • 重载,参数不同的同名函数,不关心返回值。并不是两个函数的名字相同就能构成重载。全局函数和类的成员函数同名不算重载,因为函数的作用域不同。对于函数重载,out(float a)和out(int a), 当调用out(1)时,是正确的;当调用out(0.5)时,编译错误,因为编译器无法确定应该如何进行类型转换。
  • 隐藏,是指派生类的函数屏蔽了与其同名的基类函数,注意只要同名函数,不管参数列表是否相同,基类函数都会被隐藏。
  • 覆盖,重写的基类中被重写的函数必须有virtual修饰。
  • 函数重载只是静态多态性,在编译阶段,给不同的函数不同的函数名,而虚函数实现运行时多态。
2.1 重载、重写、隐藏补充
  • 重载
    成员函数被重载的特征:
    1. 相同的范围(在同一个类中)
    2. 函数名字相同
    3. 参数不同
    4. virtual 关键字可有可无

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

  • 令人迷惑的隐藏规则
    区别重载与覆盖并不困难,但是C++的隐藏规则使问题复杂性陡然增加。这里“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下:

    1. 如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意不能与重载混淆)。
    2. 如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意不能与覆盖混淆)。
  • 如果同一个类中,是重载,父类和子类,函数名字相同参数相同,有virtual是覆盖,没有就是隐藏。

3. 内联函数
  • 在函数前面加上inline进行声明。
  • 内敛函数在函数调用位置处直接展开。
  • 内联函数可以避免函数调用时的开销,保存寄存器恢复寄存器之类的。适合于规模较小的函数。
  • 关键字inline必须与函数定义体放在一起才能使函数成为内联,仅将inline放在函数声明前面不起任何作用。inline是一种“用于实现的关键字”,而不是一种“用于声明的关键字”。
3.1内联函数相比较于 #define定义函数aa()有什么优点
  • 代码放到符号表中,用到的时候直接进行替换。
  • 编译器可以对它进行参数检查。
  • inline可以是类的成员函数,对类内成员进行访问。

4.函数指针(c++ primer第五版 p221)

5.const成员函数

  • const放在函数的后面,只能用在类中,代表该函数不可修改类中的变量。
  • const aa(类)只能调用const函数。

6.父类指针指向子类对象问题

  • 到底调用那个函数要根据指针的原型来确定,而不是根据指针实际指向的对象类型确定,即指针是什么类型,就调用什么类型的函数。
  • 虚函数除外,虚函数调用最根源的函数,对象是什么类型,就调用相应的函数。

7. C++各个存储区

8. 接7 , 对 static的讨论

  • static 放在静态存储区,并不随着函数释放空间。
  • 规定作用域。
void fun()
{
      static int a = 10;
      cout << "fun " << a << endl;
}
void fun2()
{
      static int b = 12;
      cout << "fun2 " << b++ << endl;
}
int main()
{
      fun();
      fun2();
      fun2();
      getchar();
      return 0;
}
  • 输出:10,12,13.

  • char st[10] = “abcde”,在内存中存在两份拷贝,一份在常量存储区上,一份在栈上,函数退出之后,栈上内存释放,如果想让栈上的存储区不释放,可以将其声明为static放在静态存储区上。

9. 如何去掉const变量的const特性。

  • 利用const_cast去除掉const的特性。

10. static_cast是强制类型转换的关键字,类似于c语言中的(int)a, static_cast a 等价于(int)a

11. 程序错误处理

对输入输出,用断言,用异常处理机制。

12. C++构造函数,拷贝构造函数

  1. 问题引入:
class A;
A a;
A b = a 与 A b(a); b  a    有什么区别?
  1. 解答:
  • A b = a 与 A b(a)代表着相同的意义,这里调用拷贝构造函数,拷贝构造函数如果没有重载的话,默认为浅拷贝。
  • 构造函数调用的次序,先父类,子类。析构函数的顺序,先子类后父类。

13. c++中private protected public

  • private 成员只能被本类成员(类内)和 友元访问,不能被派生类访问。
  • protected成员可以被派生类访问。
  • public 继承:基类public成员,protected成员,private成员访问属性在派生类中分别变成:public,protected,private
  • protected继承:基类public 成员,protected成员,private成员访问属性在派生类中分别变成:protected,protected,private
  • private继承:基类public成员,protected成员,private成员的访问属性在派生类中分别变成:private,private,private。

14.当数组作为函数参数输入时,数组自动转化为指针,指针大小就等于一个字的大小,根据电脑位数而定

15.const char * p1等容易混淆的概念

  • const char * p1 = “hello”;
  • char * const p2 = “hello”;
  • 。。* 翻译成为point to,从右往左读,便可知道这个是什么。
  • 指针常量,是指向常量的指针。
  • 常量指针,是指针就是个常量。

16.那些运算符不能被重载

  • ::
  • .
  • ?:

17.类方法,指的是类的静态方法,即static关键字修饰方法。

静态方法只能使用该静态方法所在类的静态数据成员和静态方法。这是因为使用静态方法时,该静态方法所在类可能还没有对象。静态方法中没有this指针。
总结:

  • 出现在类体外的函数不能指定关键字static;
  • 静态成员之间可以互相访问,包括静态成员函数访问静态数据成员和访问静态成员函数;
  • 非静态成员函数可以任意访问静态成员函数和静态成员;
  • 静态成员函数不能访问非静态成员函数和非静态数据成员;
  • 由于没有this指针的额外开销,因此静态成员函数与类的全局函数相比,速度上会有少许增长;静态成员函数里面不允许使用this 指针。

18、reinterpret_cast (expression)

reinterpret_cast运算符是用来处理无关类型之间的转换;它会产生一个新的值,这个值会有与原始参数(expressoin)有完全相同的比特位。

20、运算符重载

  • c++重载运算符的时候,返回的是引用还是值,这个取决于返回运算符本身,如果需要返回运算符本身的值就是引用(即左值)【比如,=系列,+=,-=,=,/= 】,如果不能返回值本身就需要返回值(如:= - /等)。
  • 在类外部时候,重载运算符如下,声明为友元函数。这个如果不声明为友元,放在类内,codeblocks会报错,类内只接受一个参数或者0个参数
    如:类外 friend classType operator+(classType& left, classType& right);
    类内 classType operator+(classType& right );
    在这里插入图片描述

21. new一个内存然后free会产生什么问题

  • delete会调用析构函数,free不会调用,会出现内存溢出问题。
  • 如果用free释放“new 创建的动态对象”,那么该对象因无法执行析构函数而可能导致程序出错。如果用delete释放“malloc申请的动态内存”,理论上讲程序不会出错,但是该程序的可读性很差。所以new/delete必须配对使用,malloc/free也一样。

22. new,malloc最多分配多大空间

  • 理论上是内存的大小,如果是32位,最大就是4G,但是实际中,会小一些,因为运行时的限制。

23.运行时,栈空间多大?

跟os有关,比如windows,在链接时确定栈的大小(可以由连接器的选项指定,如果未指定则使用默认值1MB),VS2013开辟的默认栈空间是1MB。

24.static全局变量与普通变量的一个区别

  • 这两者的区别在于非静态全局变量的作用域是整个源程序,当一个源程序有多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。而静态全局变量则限制了其作用域,即只在定义该变量的源文件内有效,在同一源程序的其他源文件中不能使用它。

25. 全局变量,静态全局变量,默认初值为0或者null

  • 全局变量和static变量就是这种方式分配内存的。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。

26.编译原理理解记录

  • 程序编写到运行需要经历预编译,编译,链接,生成exe等阶段。.cpp与.h的作用在于.h中进行声明,cpp在编译的时候,遇到声明会做一个标记,然后在链接的时候会找到相应的函数。每个cpp是单独编译的。不然编译顺序不同,结果不同了。
  • .h中不要包含变量的定义,因为定义后,如果多个cpp引用这个变量,在链接阶段会出现重复定义。一个工程中,是不会出现一模一样的函数定义的,那样会在链接的时候会报错。

27. string find()返回类型

  • string::size_type 为find返回的类型,如果只是使用int,容易出错,对于跨机器效果不好。
  • size_type为string和vector的find的返回类型,需要注意。
  • npos为find的失败返回值。

28.const修饰类中变量问题

  • 有时我们希望某些常量只在类中有效,所以想当然地觉得应该用const修饰数据成员来实现。但是const数据成员只在某个对象生命期内是常量,而对于整个类而言却是可变的,因为类可以创建多个对象,不同的对象const数据成员的值可以不同。
  • 所以不能在类的声明中初始化const数据成员。因为类的对象未被创建,编译器还不知道SIZE的值是多少。const数据成员的初始化只能在类构造函数的初始化表中进行。
  • 如果想建立在整个类中都恒定的常量。const数据成员是完成不了的。应该用类中的枚举常量来实现。
   class A
   {…
     enum { SIZE1 = 100, SIZE2 = 200}; //  枚举常量
     int array1[SIZE1];
     int array2[SIZE2];
   };
  • 枚举常量不会占用对象的存储空间,它们在编译时被全部求值。枚举常量的缺点是:它的隐含数据类型是整数,其最大值有限,且不能表示浮点数(如PI=3.14159).
  • 如果非要定义非int型变量的时:可以使用静态常量: static const int size。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值