面向对象的支持是C++较C的一大区别。面向对象的几个特色是封装、继承、多态。数组
封装的目的是为了让接口和实现分离,这种是逻辑上的分离,而不是在实现时必定要分开定义interface和class。经过封装,让类的使用者直接根据须要调用相应接口便可,无需关注接口的实现细节,能够理解为是一种数据抽象。安全
最典型的理解,咱们能够结合标准模板库来思考,其中有序列式容器,关联式容器。函数
序列式容器
咱们能够不关心序列式容器内部的实现机制,无论用数组仍是用列表,可是对外提供了一致的接口,好比:push_back, pop_front等等相似的接口。设计
继承一方面是业务层面的理解,业务对象之间确实存在这样的父子关系;从代码层面为了代码复用。子类一方面可使用跟本身特性无关的父类接口,另一方面能够在自身从新定义跟本身特性相关的接口。指针
继承模式在GUI相关的技术中应用的特别多,看看MFC中的类继承体系就可知。code
可是继承并非惟一能够重用代码的途径,在我看来,组合的方式更易使用。过多的继承体系让人难以驾驭!对象
多态是统一代码的好方式,典型的用法是用父类引用或者父类指针对应各子类对象,并调用相同的函数名;经过动态绑定,运行的是各自对象的各自实现。相对于经过if else的各类判断,用多态的办法,一句话就OK。继承
在设计实现类时,有一些问题须要重点考虑。构造函数、析构函数、拷贝构造函数、赋值操做符重载。接口
构造函数负责在建立对象时,对对象成员的初始化。 这里有个注意的地方,就是初始化列表以及在构造函数体内的赋值操做。在通常状况下,这两种操做并没有区别,可是若是类成员中有const类型成员或者引用,这种只能初始化,不能赋值。生命周期
class A { public: A(int a_, int b_) { a = a_; b = b_; } private: const int a; int& b; };
error C2789: “A::a”: 必须初始化常量限定类型的对象 error C2530: “A::b”: 必须初始化引用 error C2166: 左值指定 const 对象
能够看到,这种状况下编译器会报错。
拷贝构造函数是用同类型的对象去初始化自身。通常定义格式是:
A(const A& rhs);
类的实现着本身定义相同类型不一样对象之间的拷贝行为。通常涉及到指针状况时,本身去实现该函数,比较安全;
赋值操做符是用同类型的对象给自身赋值,通常定义为:
A& operator=(const A& rhs)
对于赋值操做符,要考虑不能自身赋值自身的问题。
析构函数是当对象生命周期到达时,被自动调用的函数,非用户主动调用。若是对象中申请了资源,就在析构函数中进行释放。通常在存在继承关系的状况下,将析构函数定义为虚函数。
若是某些类的对象做者认为在内存中应该只有一份,不该该拷贝来拷贝去,那么能够将类实现为uncopyable类型。怎么实现呢?
private: A(const A& rhs); A& operator(constA& rhs);
将类的拷贝构造函数和赋值操做符设置为private便可。当发生赋值操做值,因为调用了private类型的方法,是非法操做。编译器没法经过。
新版本的C++能够经过以下方式作到禁用拷贝,将涉及到拷贝的函数声明为delete
class C { public: C(int a_, int b_) : a(a_), b(b_) {} C(const C& rhs) = delete; C& operator=(const C& rhs) = delete; int a; int b; };
当编写了拷贝代码时,编译器会报以下错误:
error C2280: “C &C::operator =(const C &)”: 尝试引用已删除的函数
在某些领域,使用面向对象方法能够很好的提炼出各类业务模型和接口,好比说作GUI,使用面向对象的方法就很是天然;在其余的系统中,咱们有时候会使用基于对象的方法去作开发,下降程序的复杂度。