c++_3: 继承和组合

面向对象

  • 封装:隐藏实现细节,使得代码模块化
  • 继承:扩展已存在的代码模块(类);它们的目的都是为了—代码重用
  • 多态:是为了实现另一个目的——接口重用!

封装

继承

  • 从一般到特殊
  • 通过继承创建的新类称为“子类”或“派生类”。被继承的类称为“基类”、“父类”或“超类”。要实现继承,可以通过“继承”(Inheritance)和“组合”(Composition)来实现。

多态

  • 是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,允许将子类类型的指针赋值给父类类型的指针。
  • 虚函数

C++的代码重用

  • 组合
  • 继承
  • 类模板

类之间的关系

http://blog.csdn.net/qmroom/article/details/3083928
http://www.360doc.com/content/11/0614/14/935385_126863863.shtml

  • 纵向:继承
  • 横向:依赖+关联+聚合+组合
  • 强弱关系:依赖<关联<聚合<组合

依赖

  • 符号: >
  • 关系:”….uses a …”
  • 指C5可能要用到C6的一些方法,也可以这样说,要完成C5里的所有功能,一定要有C6的方法协助才行。C5依赖于C6的定义,一般是在C5类的头文件中包含了C6的头文件。
  • 注意,要避免双向依赖。一般来说,不应该存在双向依赖。
  • 一般是A中的某个方法把B的对象作为参数使用(假设A依赖于B)。
//C5.h
class C5 
...{

};

// C6.h
#include "C5.h"

class C6
...{

};

关联

  • 符号: >
  • 关系:”….has a …”
  • C1-C2:指双方都知道对方的存在,都可以调用对方的公共属性和方法。
  • 关联在代码的表现为双方都拥有对方的一个指针,当然也可以是引用或者是值。
class C3 
...{
public:
    C4* theC4;

};

class C4 
...{

};

聚合

  • 符号: >
  • 关系:”….owns a …”
  • 聚合:表示C9聚合C10,但是C10可以离开C9而独立存在
class C9 
...{
public:
    C10 theC10;

};

class C10 
...{

};

组合

  • 符号: >
class C7 
...{
public:
    C8 theC8;

};

class C8 
...{
};

组合和愈合的关系

视问题域而定的,例如在关心汽车的领域里,轮胎是一定要组合在汽车类中的,因为它离开了汽车就没有意义了。但是在卖轮胎的店铺业务里,就算轮胎离开了汽车,它也是有意义的,这就可以用聚合了。

关联,依赖,组合,聚合

  • 关联是类之间的一种关系,例如老师教学生,老公和老婆,水壶装水等就是一种关系。这种关系是非常明显的,在问题领域中通过分析直接就能得出。
  • 依赖是一种弱关联,只要一个类用到另一个类,但是和另一个类的关系不是太明显的时候(可以说是“uses”了那个类),就可以把这种关系看成是依赖,依赖也可说是一种偶然的关系,而不是必然的关系,就是“我在某个方法中偶然用到了它,但在现实中我和它并没多大关系”。例如我和锤子,我和锤子本来是没关系的,但在有一次要钉钉子的时候,我用到了它,这就是一种依赖,依赖锤子完成钉钉子这件事情。
  • 组合是一种整体-部分的关系,在问题域中这种关系很明显,直接分析就可以得出的。例如轮胎是车的一部分,树叶是树的一部分,手脚是身体的一部分这种的关系,非常明显的整体-部分关系。

所谓的这些关系只是在某个问题域才有效,离开了这个问题域,可能这些关系就不成立了,

组合

  • 新类中创建已经存在的类; 嵌入的子类被视为私有
  • “….. is a part of……”
class x { 
    int i;
   public:
     X(){i=0;}
     void set(int ii) {i=ii;}
     int read() const {return i;}
     int permute (){return i=i*47;}
};

class Y {
    int i;
   public:
     X x;
     Y();
     void f(int ii) {i=ii};
     int g() const {return i;}
};

int main()
{
    Y y;
    y.f(47);
    y.x.set(37);   //初始化x类
}

继承(is-a)

泛化

class x
{ 
    int i;
   public:                     //若为private则不可被子类调用
     X(){i=0;}
     void set(int ii) {i=ii;}   //被Y的函数覆盖
     int read() const {return i;}
     int permute (){return i=i*47;}
};

class Y :public X{
   int i;  //不同于X的i
public:
   Y(){i=0;}
   int change()
   {
      i=premute();
      return i;
   }
   void set(int ii)    //覆盖x的set函数
   {
       i=ii;
       X::set(ii);
   }
};

int main()
{
    Y D;
    D.change();
    D.read();       //调用基类的read函数
    D.premute();
    D.set(12);      //覆盖了基本的set函数
    D.X::set(12);  //调用被子类覆盖的基类的函数
 }
  • sizeof(Y)=2倍 sizeof(X)
  • 子类调用基类方法,需要基类的成员函数不是私有的
  • 基类指针/引用可以再不进行显示转换的情况下指向派生类对象;

私有继承

http://www.cnblogs.com/qlwy/archive/2011/08/25/2153584.html

class A
{};
class B :public A;
class C:private A;
class D:protected A;
- public protected private
共有继承 public protected 不可见
私有继承 private private 不可见
保护继承 protected protected 不可见

向上类型转换(强制转化之一)

  • 基类指针/引用可以再不进行显示转换的情况下指向派生类对象;
class RatedPlaer:public TableTennisPlayer
{};

RatedPlayer rplayer1(1140,"m");
TableTennisPlayer &rt=rplayer;
TableTennisPlayer *pt=&rplayer;

rt.Name(); //调用基类TableTennisPlayer的Name
pt->Name(); //调用基类TableTennisPlayer的Name

你可能感兴趣的:(c++_3: 继承和组合)