OOP[GeekBand]

1 面向对象的三把大刀 -复合、委托和继承

1.1复合(Composition)

1.1.1 定义

复合表示的是has-a的关系。在实现类中包含有复合类的一个完整实体,是一种类与类之间强的关系。在UML图示中用实心菱形表示。代码示例如下:

class A;
class B{A a;}

1.1.2 复合关系下的构造和析构

  • 构造由内而外
    复合关系下的构造函数,先执行复合类的默认构造函数,在执行自身的构造函数体。如果不希望调用复合类的默认构造函数或者复合类没有默认构造函数,则要在初始化列表中做显示的初始化。如下:
class A{
    int x;
public:
    A(int _x):x(_x){}
}
class B{
    A a;
    int _y;
public:
    B(int x,int y):a(x),_y(y){}
};
  • 析构由外而内
    复合关系下的构造函数,先执行自身的析构函数,在执行复合类的析构函数。

1.2 委托(Delegation) Composition by reference

委托表示的也是has-a的关系。在实现类中包含有委托类的一个引用,是类与类之间比较弱的关系,在UML图示中用空心棱形表示。代码示例如下:

class A;
class B{
    A *p;
}

1.3 继承(Inheritance)

1.3.1 定义

类通过继承联系在一起构成一种层次结构。在这种层次结构中,顶层的类叫做父类或基类;其他类则直接或间接的从基类继承而来,这些继承而来的类称为派生类或子类。在UML图示中用空心三角形表示。
在C++中,继承有三种实现方式,公有继承(public),保护继承(protected)和私有(private)继承。通过在类派生列表中指定。派生列表的形式为class drived_class:public A,protected B,private C。类派生列表中的访问说明符并不影响直接子类访问父类的成员,而是限制子类的客户访问基类的成员。也就是说,当使用Private继承基类C时,子类依然可以访问父类C的公有成员和保护成员,但是子类的子类及子类的调用者则无法访问基类C中的所有成员,包括C中的公有成员。因为,子类按Private从父类继承成员时,将父类所有的成员都继承为自己的Private成员,因此类的用户就无法调用。
注意:一般情况下,都是用Public继承,Protected和private很少用。

1.3.2 继承关系下的构造和析构

  • 构造由内而外
    继承关系下的构造函数,先执行父类的默认构造函数,在执行自身的构造函数体。如果不希望调用复合类的默认构造函数或者复合类没有默认构造函数,则要在初始化列表中做显示的初始化。如下:
class A{
    int x;
public:
    A(int _x):x(_x){}
}
class B:public A{
    A a;
    int _y;
public:
    B(int x,int y):a(x),_y(y){}
};
  • 析构由外而内
    继承关系下的构造函数,先执行自身的析构函数,在执行父类的析构函数。

2 虚函数与多态

2.1 虚函数

2.1.1 虚函数定义

对于某些函数,如果基类希望子类实现符合各自需求的版本,那就可以把这些函数声明为虚函数。子类必须在其内部实现中队重新定义的虚函数进行声明。声明虚函数时,需要在函数声明的前面添加virtual,如virtual void a_virt_func();

2.1.2 虚函数使用场景

  • non-virtual函数
    你不希望子类重新定义(override)父类的函数。
  • virtual函数
    你希望子类重新定义(override)它,但是希望它有默认定义。
  • pure virtual函数
    你希望子类重新定义(override)它,但是对他没有默认的定义。

2.2 多态

多态是OOP的核心思想,意思为“多种形式”。我们把具有继承关系的多个类型称作多态类型,因为我们能使用这些类型的“多种形式”而无须在意他们之间的差异。在C++中,引用和指针的动态类型和静态类型的不一致正是实现这一机制的关键。

参考资料:

1.GeekBand课件
2.cpp primer 5th edition

你可能感兴趣的:(OOP[GeekBand])