您的位置:首页 > 其它

类之间的关系

2015-09-18 17:45 260 查看
在类之间最常见的关系是

依赖(use-a)

聚合(has-a)也称为复合(composition)

继承(is-a)

表达类关系的UML连接图



在订单处理系统中:

order:订单

Item: 项目

Account:账户

依赖

order类使用Account类,因为必须访问Account对象查看信用状态,但是Item类不依赖于Account类。

聚合(aggregation)或复合(composition)

比如,一个order对象包含一些Item对象

又比如

class Address{...};
class PhoneNumber{...};
class Person{
public:
...
private:
std::string name;
Address address;
PhoneNumber voiceNumber;
PhoneNumber  faxNumber;
}


(条款38)

继承(is-a)

比如RushOrder类继承自Order类,在RushOrder类中包含一些用于优先处理的特殊方法。

public继承 意味着is-a,适用于base classes身上的每一件事情一定也适用于derived classes身上,因为每一个derived class对象也都是一个base class对象(条款32)

那么private继承呢?

如果classes之间的继承关系是private,那么编译器不会自动将一个derived class对象转换成一个base class对象,这和public继承不同,由private继承的所有成员,在derived class中会变成private属性。

private继承意味着根据某物实现出,如果D以private继承自B,意思是D对象根据B对象实现而得,其意义只及于软件实现层面,没有其他意义。

例如:

我们想要修改Widget class,让它记录每个成员函数被调用的次数,为了完成这项工作,我们需要设定某种定时器,让我们知道收集数据的时候是否到了。

现在有一个类:

class Timer{
public :
explicit Timer(int tickFrequency);
virtual void onTick() const;
};


如果我们让widget重新定义timer内的virtual函数,Widget必须继承自Timer,但是在这里public继承并不恰当,因为它们不是is-a的关系。

我们必须以private的形式继承Timer:

class Widget: private Timer{
private:
virtual void onTick() const;
}


但是这样的设计并不是绝对必要的,我们可以用复合的方式取而代之。

class Widget{
private:
class WidgetTimer: public Timer{
public:
virtual void onTick() const;
...
};
WidgetTimer timer;
}


这个设计同时涉及到public继承和复合,并且导入了一个新的class。

private继承主要用于一个意欲成为derived class者想访问一个意欲成为base class者的protected的成分,或者为了重新定义一个或多个virtual函数,这两个class之间是is-implemented-in-term-of 而非is-a 的关系。

还有一种情况,就是涉及到空间最优化时,可能会让你选择private 继承而不是继承加复合。

class Empty{};
class HoldsAnInt{
private:
int x;
Empty e;
}


你会发现sizeof(HoldsAnInt)>sizeof(int)

class HoldsAnInt:private Empty{
private:
int x;
}


可以确定sizeof(HoldsAnInt)==sizeof(int),这就是空白基类最优化(EBO),这对对象尺寸最小化的程序开发者而言可能很重要(条款39)

资料来源:

Java 核心技术卷 1

Effective C++
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: