您的位置:首页 > 编程语言 > C语言/C++

c++_3: 继承和组合

2015-12-07 11:14 274 查看

面向对象

封装:隐藏实现细节,使得代码模块化

继承:扩展已存在的代码模块(类);它们的目的都是为了—代码重用

多态:是为了实现另一个目的——接口重用!

封装

继承

从一般到特殊

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

多态

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

虚函数

C++的代码重用

组合

继承

类模板

类之间的关系

/article/9341126.html

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)

子类调用基类方法,需要基类的成员函数不是私有的

基类指针/引用可以再不进行显示转换的情况下指向派生类对象;

私有继承

/article/5110083.html

class A
{};
class B :public A;
class C:private A;
class D:protected A;


-publicprotectedprivate
共有继承publicprotected不可见
私有继承privateprivate不可见
保护继承protectedprotected不可见

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

基类指针/引用可以再不进行显示转换的情况下指向派生类对象;

class RatedPlaer:public TableTennisPlayer
{};

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

rt.Name(); //调用基类TableTennisPlayer的Name
pt->Name(); //调用基类TableTennisPlayer的Name
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: