1. 继承方式

  • public      父类的访问级别不变
  • protected    父类的public成员在派生类编程protected,其余的不变
  • private        父类的所有成员变成private
  1. #include <iostream>
  2. using namespace std;
  3. class base
  4. {
  5. public:
  6. void printa()
  7. { cout <<"base"<< endl; }
  8. protected:
  9. void printhello()
  10. { cout <<"helo"<< endl; }
  11. private:
  12. void printnohello()
  13. { cout <<"no hello"<< endl; }
  14. };
  15. class derived : public base
  16. {
  17. public:
  18. void printb() { printhello(); }
  19. // void printc() { printnohello(); } //printnohello是父类的私有函数,不可访问
  20. };
  21. int main()
  22. {
  23. base a;
  24. a.printa();
  25. //a.printhello(); //printhello是类derived的protected函数,不可访问。
  26. }

2. sizeof 和 strlen 的区别

  • sizeof 是一个操作符,strlen 是库函数。
  • sizeof 的参数可以是数据的类型,也可以是变量,而 strlen 只能以结尾为‘\ 0‘的字符串作参数。
  • 编译器在编译时就计算出了sizeof 的结果。而strlen 函数必须在运行时才能计算出来。并且 sizeof计算的是数据类型占内存的大小,而 strlen 计算的是字符串实际的长度。
  • 数组做 sizeof 的参数不退化,传递给 strlen 就退化为指针了。
  1. #include <iostream>
  2. #include <cstdlib>
  3. #include <cstring>
  4. using namespace std;
  5. int main()
  6. {
  7. int a[] = {1, 2, 3, 4, 5};
  8. cout << sizeof(a) << endl; //20
  9. // cout << strlen(a) << endl;
  10. char b[] = {'a', 'b'};
  11. cout << strlen(b) << endl; //6
  12. cout << sizeof(b) << endl; //2
  13. }

3. C中的 malloc 和C++中的 new 有什么区别

  • new、delete 是操作符,可以重载,只能在 C++中使用。
  • malloc、free 是函数,可以覆盖,C、C++中都可以使用。
  • new  可以调用对象的构造函数,对应的 delete 调用相应的析构函数。
  • malloc 仅仅分配内存,free 仅仅回收内存,并不执行构造和析构函数
  • new、delete 返回的是某种数据类型指针,malloc、free 返回的是 void 指针。

注意:malloc 申请的内存空间要用 free 释放,而 new 申请的内存空间要用 delete 释放,不要混用。

因为两者实现的机理不同。

4.1. c/c++中static

要理解static,就必须要先理解另一个与之相对的关键字auto,其实我们通常声明的不用static修饰的变量,都是auto的,因为它是默认的。auto的含义是由程序自动控制变量的生存周期,通常指的就是变量在进入其作用域的时候被分配,离开其作用域的时候被释放;而static就是不auto,变量在程序初始化时被分配,直到程序退出前才被释放;也就是static是按照程序生命周期来分配释放变量的,而不是变量自己的生命周期;所以,像这样的例子:

  1. void func()
  2. {
  3. int a;
  4. static int b;
  5. }

每一次调用该函数,变量a都是新的,因为它是在进入函数体的时候被分配,退出函数体的时候被释放,所以多个线程调用该函数,都会拥有各自独立的变量a,因为它总是要被重新分配的;而变量b不管你是否使用该函数,在程序初始化时就被分配的了,或者在第一次执行到它的声明的时候分配(不同的编译器可能不同),所以多个线程调用该函数的时候,总是访问同一个变量b,这也是在多线程编程中必须注意的!

static的全部用法:

1.类的静态成员:

  1. class A
  2.  
  3. {
  4. private:
  5. static int s_value;
  6. };

在cpp中必须对它进行初始化:int A::s_value = 0;  // 注意,这里没有static的修饰!

类的静态成员是该类所有实例的共用成员,也就是在该类的范畴内是个全局变量,也可以理解为是一个名为A::s_value的全局变量,只不过它是带有类安全属性的;道理很简单,因为它是在程序初始化的时候分配的,所以只分配一次,所以就是共用的;

类的静态成员必须初始化,道理也是一样的,因为它是在程序初始化的时候分配的,所以必须有初始化,类中只是声明,在cpp中才是初始化,可以在初始化的代码上放个断点,在程序执行main的第一条语句之前就会先走到那;如果你的静态成员是个类,那么就会调用到它的构造函数;

2.类的静态函数:

  1. class A
  2. {
  3. private:
  4. static void func(int value);
  5. };

实现的时候也不需要static的修饰,因为static是声明性关键字;类的静态函数是在该类的范畴内的全局函数,不能访问类的私有成员,只能访问类的静态成员,不需要类的实例即可调用;实际上,它就是增加了类的访问权限的全局函数:void A::fun(int);

静态成员函数可以继承和覆盖,但无法是虚函数;

3.只在cpp内有效的全局变量:

在cpp文件的全局范围内声明:static int g_value = 0;

这个变量的含义是在该cpp内有效,但是其他的cpp文件不能访问这个变量;如果有两个cpp文件声明了同名的全局静态变量,那么他们实际上是独立的两个变量;

如果不使用static声明全局变量:int g_value = 0;

那么将无法保证这个变量不被别的cpp共享,也无法保证一定能被别的cpp共享,因为要让多个cpp共享一个全局变量,应将它声明为extern(外部)的;也有可能编译会报告变量被重复定义;总之不建议这样的写法,不明确这个全局变量的用法;

如果在一个头文件中声明:static int g_vaule = 0;

那么会为每个包含该头文件的cpp都创建一个全局变量,但他们都是独立的;所以也不建议这样的写法,一样不明确需要怎样使用这个变量,因为只是创建了一组同名而不同作用域的变量;

这里顺便说一下如何声明所有cpp可共享的全局变量,在头文件里声明为extern的:

extern int g_value; // 注意,不要初始化值!

然后在其中任何一个包含该头文件的cpp中初始化(一次)就好:

int g_value = 0; // 初始化一样不要extern修饰,因为extern也是声明性关键字;

然后所有包含该头文件的cpp文件都可以用g_value这个名字访问相同的一个变量;

4.2 Cstatic有什么作用

  • 隐藏。当我们同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性,故使用static在不同的文件中定义同名函数和同名变量,而不必担心命名冲突。
  • 保持变量内容的持久。存储在静态数据区的变量会在程序刚开始运行时就完成初始化,也是唯一的一次初始化。共有两种变量存储在静态存储区:全局变量和static变量。
  • 默认初始化为0.其实全局变量也具备这一属性,因为全局变量也存储在静态数据区。在静态数据区,内存中所有的字节默认值都是0×00,某些时候这一特点可以减少程序员的工作量。

5. 简述C\C++程序编译的内存情况分配

C、C++中内存分配方式可以分为三种:

(1)从静态存储区域分配:内存在程序编译时就已经分配好,这块内存在程序的整个运行期间都存在。速度快、不容易出错,因为有系统会善后。例如全局变量,static变量等。

(2)在栈上分配:在执行函数时,函数内局部变量的存储单元都在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。

(3)从堆上分配:即动态内存分配。程序在运行的时候用 malloc 或 new 申请任意大小的内存,程序员自己负责在何时用 free 或 delete 释放内存。动态内存的生存期由程序员决定,使用非常灵活。如果在堆上分配了空间,就有责任回收它,否则运行的程序会出现内存泄漏,另外频繁地分配和释放不同大小的堆空间将会产生堆内碎块

一个 C、C++程序编译时内存分为 5 大存储区:堆区、栈区、全局区、文字常量区、程序代码区。

6. 面向对象的三大特征

  • 封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。
  • 继承,是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。通过继承创建的新类称为“子类”或“派生类”。继承的过程,就是从一般到特殊的过程。要实现继承,可以通过“继承”和“组合”来实现。
  • 多态,简单的说,就是一句话:允许将指向子类类型的指针赋值给父类类型的指针。实现多态,有二种方式,覆盖,重载。
    • 覆盖,是指子类重新定义父类的虚函数的做法。
    • 重载,是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。

总结:作用

  • 封装可以隐藏实现细节,使得代码模块化
  • 继承可以扩展已存在的代码模块(类);它们的目的都是为了——代码重用
  • 多态则是为了实现另一个目的——接口重用!多态的作用,就是为了类在继承和派生的时候,保证使用“家谱”中任一类的实例的某一属性时的正确调用。

7. 简述多态的实现原理

编译器发现一个类中有虚函数,便会立即为此类生成虚函数表vtable。虚函数表的各表项为指向对应虚函数的指针。编译器还会在此类中隐含插入一个指针 vptr指向虚函数表。调用此类的构造函数时,在类的构造函数中,编译器会隐含执行 vptr 与 vtable 的关联代码,将 vptr 指向对应的 vtable,将类与此类的 vtable 联系了起来。另外在调用类的构造函数时,指向基础类的指针此时已经变成指向具体的类的 this 指针,这样依靠此 this 指针即可得到正确的 vtable。

如此才能真正与函数体进行连接,这就是动态联编,实现多态的基本原理。

注意:一定要区分虚函数,纯虚函数、虚拟继承的关系和区别。牢记虚函数实现原理,因为多态C++面试的重要考点之一,而虚函数是实现多态的基础。

8. c++空类的成员函数

  • 缺省的构造函数
  • 缺省的拷贝构造函数
  • 缺省的赋值运算符
  • 缺省的析构函数
  • 缺省的取址运算符
  • 缺省的取址运算符const

注意:只有当实际使用这些函数的时候,编译器才会去定义它们。

9. 谈谈你对拷贝构造函数和赋值运算符的认识

两个不同之处:

  • 拷贝构造函数生成新的类对象,而赋值运算符不能。
  • 由于拷贝构造函数是直接构造一个的类对象,所以在初始化这个对象之前不用检验源对象是否和新建对象相同。而赋值运算符则需要这个操作,另外赋值运算中如果原来的对象中有内存分配要先把内存释放掉。

注意:当有类中有指针类型的成员变量时,一定要重写拷贝构造函数和赋值运算符,不要使用默认的。

10. 用 C++设计一个不能被继承的类

  1. class Base
  2. {
  3. private:
  4. Base() {}
  5. ~Base() {}
  6. };
  7. class Derived : public Base
  8. {
  9. public:
  10. Derived() : Base() {}
  11. ~Derived() {}
  12. };

c++ 中的流对象就是采用这样的原理。防止被赋值、复制。

11. 类成员的重写、重载和隐藏的区别

重写和重载主要有以下几点不同

  • 范围的区别:被重写的和重写的函数在两个类中,而重载和被重载的函数在同一个类中。
  • 参数的区别:被重写函数和重写函数的参数列表一定相同,而被重载函数和重载函数的参数列表一定不同。
  • virtual 的区别:重写的基类中被重写的函数必须要有 virtual 修饰,而重载函数和被重载函数可以被virtual 修饰,也可以没有。

隐藏和重写、重载有以下几点不同

  • 与重载的范围不同:和重写一样,隐藏函数和被隐藏函数不在同一个类中
  • 参数的区别:隐藏函数和被隐藏的函数的参数列表可以相同,也可不同,但是函数名肯定要相同。当参数不相同时,无论基类中的参数是否被 virtual 修饰,基类的函数都是被隐藏,而不是被重写

说明:虽然重载和覆盖都是实现多态的基础,但是两者实现的技术完全不相同,达到的目的也是完全不同的,覆盖是动态绑定的多态,而重载是静态绑定的多态。

12. extern 有什么作用

extern 标识的变量或者函数声明其定义在别的文件中,提示编译器遇到此变量和函数时在其它模块中寻找其定义。

13. 引用和指针区别

  • 引用必须被初始化,但是不分配存储空间。指针不必在声明时初始化,在初始化的时候需要分配存储空间
  • 引用初始化以后不能被改变,指针可以改变所指的对象
  • 不存在指向空值的引用,但是存在指向空值的指针

14. 数组指针

  1. #include <iostream>
  2. using namespace std;
  3. int main()
  4. {
  5. int a[5] = {1, 2, 3, 4, 5};
  6. int *ptr = (int*)(&a+1);
  7. cout << *(ptr-1) << "\t" << *(ptr-2) << endl; // 5 4
  8. cout << "----------------" << endl;
  9. int *p = (int *)(a+1); //2
  10. cout << *p << endl;
  11. }

15. const int *a  和 int * const a 区别

  1. int main()
  2. {
  3. int b = 3;
  4. int c = 4;
  5. const int *p = &b; //等价于 int const *p = &b;
  6. p = &c; //修饰值,指针可变
  7. //*p = 5;//error 修饰值,值不可变
  8. cout << *p << endl;
  9.  
  10. int a = 5;
  11. int * const q = &a; //修饰指针
  12. //p = &c;//error修饰指针,指针不可变
  13. *p = 5; //修饰指针,值可变
  14. }

[转帖]c++ 面试整理的更多相关文章

  1. 就目前市面上的面试整理来说,最全的BAT大厂面试题整理在这

    原标题:就目前市面上的面试整理来说,最全的BAT大厂面试题整理在这 又到了面试求职高峰期,最近有很多网友都在求大厂面试题.正好我之前电脑里面有这方面的整理,于是就发上来分享给大家. 这些题目是网友去百 ...

  2. 面试整理之DOM事件阶段

    因为快面试了,打开<JavaScript高级程序设计>,对DOM事件进行整理了下 本文主要解决的问题: 事件流 DOM事件流的三个阶段 先理解流的概念 在现今的JavaScript中随处可 ...

  3. java面试整理(会持续更新..)

    本人出道至今,经历了大大小小百余场战斗,,,下面整理的面试题有些有答案,有些没答案,那个谁说过:"要抱着怀疑的态度去编程,所以,即便有答案,也不一定正确,即便我本地正确,但是由于屏幕前的你和 ...

  4. 面试整理(1):原生ajax

    接到电话面试,有一些送分题答的不好,在这里整理一下 问题:原生ajax的工作流程是怎么样的? 老用封装好的工具,原生的ajax其实并不熟悉,今天复习一下.主要参考http://www.w3school ...

  5. java面试整理

    IO和NIO的区别 这是一个很常见的问题,如果单纯的只回答IO和NIO的区别,只能算及格.我个人觉得应该从以下几个方面回答: 1).IO简介, 2).TCP的三次握手,因为这也是两者的区别之一, 3) ...

  6. java核心技术面试整理

    [前方高能,是这半年BAT,京东,远景,华为,中兴以及苏研发中心被问到的Java公共问题的一个整理] ------------------------------------------------- ...

  7. 年底Android面试整理(附答案)

    面试,无非都是问上面这些问题(挺多的 - -!),聘请中高级的安卓开发会往深的去问,并且会问一延伸二.以下我先提出几点重点,是面试官基本必问的问题,请一定要去了解! 基础知识 – 四大组件(生命周期, ...

  8. [转帖]GitHub上整理的一些工具

    GitHub上整理的一些工具   技术站点 Hacker News:非常棒的针对编程的链接聚合网站 Programming reddit:同上 MSDN:微软相关的官方技术集中地,主要是文档类 inf ...

  9. c++ 面试整理

    1. 继承方式 public    父类的访问级别不变 protected    父类的public成员在派生类编程protected,其余的不变 private        父类的所有成员变成pr ...

随机推荐

  1. git巧妙命令行

    git cherry-pick c7081607cfd1bfa99b6e6c70c208e71fbd8767ae

  2. leetcode算法学习----逆波兰表达式求值(后缀表达式)

    下面题目是LeetCode算法:逆波兰表达式求值(java实现) 逆波兰表达式即后缀表达式. 题目:  有效的运算符包括 +, -, *, / .每个运算对象可以是整数,也可以是另一个逆波兰表达式.同 ...

  3. 分析helo1项目中的 Web.xml

    web.xml文件位于hello1 中target/WEB-INF/classes/javaeetutorial目录下. 这个web.xml文件包含Facelets应用程序所需的几个元素: 其中(1) ...

  4. - > 动规讲解基础讲解三——混合背包(背包模板)

    将01背包,完全背包,和多重完全背包问题结合起来,那么就是混合三种背的问题 根据三种背包的思想,那么可以得到混合三种背包的问题可以这样子求解 for(int i=1; i<=N; ++i) if ...

  5. 1. PermCheck 桃花顺检验 Check whether array A is a permutation.

    package com.code; import java.util.Arrays; public class Test04_2 { public static int solution(int[] ...

  6. Ubuntu 10.04.3 挂载NTFS移动硬盘

    1: fdisk -l #查看所有连接到电脑上的储存设备 2:  mkdir -p /mnt/需要掛的分區 #在mnt裏建立準備掛載分區的目錄 3:  mount -t ntfs /dev/需要掛的分 ...

  7. cocos2d-x 多触点监听

    [cpp] view plaincopy //首先到cocos2d-x项目下的ios目录下.找到AppController.mm文件,在函数 didFinishLaunchingWithOptions ...

  8. 3736 【HR】万花丛中2

    3736 [HR]万花丛中2  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解       题目描述 Description HR神犇在成功攻略ZX后,花心 ...

  9. C# 获得资源文件下图片的路径

    最终实现正确的代码是: button8.Image = System.Drawing.Image.FromFile(@"..\\..\\Resources\\GAOJIBAN.png&quo ...

  10. Application.StartupPath获取执行文件路径substring()取特定长度字符串取得根目录

    Application.StartupPath获取执行文件路径substring()取特定长度字符串取得根目录 2012-07-20 10:48 257人阅读 评论(0) 收藏 举报 path usi ...