程序员面试宝典第10章面向对象+个人理解版整理笔记

因为找实习,很多公司都要看技术博客,大部分笔记,BUG修复之类的都写在印象笔记上,现在开始往上面搬。
1.面向对象编程的好处:@1.良好的可复用性
                                       @2.易维护:便于维护人员读懂源程序并修改。
                                       @3.良好的可扩展性:不外乎加入一些新的类,基本不用修改原来的东西。
2.面向对象设计的三原则:封装、继承(interface)、多态(virtual)。
封装:可以隐藏实现细节,使得代码模块化。(目的,代码重用)
继承:可以扩展已存在的代码模块(类)。(目的,代码重用)
多态:(目的,接口重用)
补充:A.里氏代换原则(复用的基石)B.开闭原则(面向对象设计的重要特性之一):软件对扩展应该是开放的,对修改应该是关闭的。(即,对于设计好的代码不要进行修改,应该进行新功能模块的开发)C.防御式编程(一种编程技巧,与面向对象编程无关):简单来说就是要把错误控制在有限的范围内。不管出了什么错,程序都不能崩溃。(每一步都做防御,无法修改时做容错)
3.什么是封装:最广为人知的例子(在OO编程中,把数据和针对该数据的操作,都统一到一个Class里)
除使用Class以外的其他封装方法:
@1.通过文件(头文件),使用#include把封装了某些类和库的头文件引入
@2.通过namespace/package/module(C++/Java/Python)进行封装
封装的好处:@1.增加代码的内聚性(内举性高,今儿提高可复用性和可维护性)
@2.还可以对外进行信息隐藏,使用private\protected之类的。
4.一个空类产生哪些类成员函数?
答案:4个成员函数:默认构造函数、析构函数、复制构造函数、赋值函数
5.struct和Class的区别(struct其实就是Class,设计意义是让C程序员便于使用,同时兼容C开发的项目)
struct和Class的区别在于,class中变量默认是private,struct中变量默认是public。
6.一个类的所有实例间共享数据,使用什么样的成员变量。
答案:必须使用静态变量。注意:不允许使用静态变量去存放某一个对象的数据,静态变量是所有对象间共享的。
如果把静态变量设置为私有变量,可以通过公有静态成员函数去访问。
7.关于初始化构造函数的初始化顺序,注意,初始化顺序是按照成员变量的声明顺序来执行的。
例如:private int m_i;
                       int m_j;
           base(int i):m_j(i),m_i(m_j);//由于m_i先声明的,所以由于m_j没有初始化,所以会分配给m_i一个随机数,然后再把I的值赋值给m_j;
8.在类中定义的常量必须在构造函数的初始化列表中初始化或者设置成static.
9.MFC类库中的CObject类,为什么Object类要定义一个虚的构造函数。
答案:因为多态的存在。
例子:CBase *pBase;
          CChild c;
          pBase=&c;//如果撤销pBase的时候,不会调用Child的析构函数,从而造成CChild的内存泄露。
将CObject的析构函数设置为Virtual型,则所有派生类的析构函数都自动变成Virtual型,保证任何情况下都不会出现由于析构函数调用不全而出现的内存泄露问题。
10.为什么构造函数不能为Virtual型的呢?
首先弄懂什么是虚函数:虚调用时一种可以在只有部分信息的情况下工作的机制。允许只知道一个接口不知道确切对象类型的情况下调用。
虚函数的声明必须与基类中定义方式完全匹配。虚函数是允许被其子类重新定义的成员函数。
区分两个概念:覆盖//是指子类重新定义父类的虚函数的做法。(与多态有关的表示),当子类重新定义父类的虚函数的时候,父类指针根据赋给它的不同的子类指针,动态地调用属于子类的该地址。(多态一定是晚绑定的,一定是静态分配的,一定是运行期绑定的)
                         重载  //是指允许存在多个同名函数,而且这些函数的参数表不同。(重载并不是OO编程的要义!重载与多态无关)
答案:然而构造函数必须知道对象的确定类型。所以构造函数不能为虚。
说明:虚函数使用需要付出代价,每个虚函数对象都必须维护一个V表,在使用虚函数时会产生一个系统开销。
补充:什么是多态?
多态性简单的描述就是:一个借口,多种方法。允许将子类型的指针赋值给父亲类型的指针。
重点描述性语言:多态性是OO编程领域的核心概念。
11.内联函数(inline关键字声明),主要作用是解决程序的运行效率。
内联函数的注意点:@1.递归函数不能定义为内联函数。
                                @2.内联函数适用(不存在While/swith的+1-5条语句)小函数
                                @3.内联函数不能进行异常的接口声明。
                                @4.析构函数可以是内联函数
                                @5.内联函数只能先定义后适用。
12.注意:单个参数的构造函数的隐含类型转换问题
例如:B(int ):data(i)//成员变量初始化列表
{cout<<“constructed  by parameter”<
}
B Play(B b)//测试写成Play(5);因为含有一个隐含类型转换,如果添加explicit 关键字会消除这种隐含转换。
{
return b;
}
13.什么时候定义复制构造函数:所有需要分配系统资源的用户定义类型都需要一个复制构造函数。
14.判断问题,哪些在编译时解析,哪些不是?
宏,内联函数,模板(都可以在编译时候解析)
虚函数(不行,它是在运行期被解析的)
15.友元(友元不是成员函数,关键字friend,作用:提高程序的运行效率。缺点:破坏了类的封装性和隐藏性)
友元可以是一个函数(友元函数)也可以是一个类(友元类)
16.异常处理
构造函数会抛出异常!:如果构造两个对象,一个构造成功,另一个构造失败,将不会调用析构就退出了,第一个构造成功的对象没有释放,从而造成了内存泄露。
处理这样的问题,智能指针是一个不错的选择。在C++中,资源泄露问题一般都使用RAII:把需要打开/关闭的资源用简单的对象封装起来。
析构函数(尽可能地不要抛出异常),可能会造成程序迷失。因为异常指针的丢失。
需要笔记分享的,可以发邮件到我邮箱,[email protected],写明需要哪一章,谢谢。

你可能感兴趣的:(C++,面试,入门,笔记)