38:通过复合塑膜出has-a或“根据某物实现出”

复合(compsosition)是类型之间的一种关系,当某种类型的对象内含它种类型的对象,便是这种关系。

例如:

class Address{/*...*/ };//某人的住址
class PhoneNumber{/*...*/ };
class Person {
public:
    //...
private:
    std::string name;//合成成分物
    Address address;//同上
    PhoneNumber voiceNumber;//同上
    PhoneNumber faxNumber;//同上
};

本例中Person对象由string,Address,PhoneNumber构成。

复合这个术语有许多同义词,包括layering(分层),containment(内含),aggregation(聚合)和embedding(内嵌)。

复合有两个意义。

复合意味has-a(有一个)或is-implemented-in-terms-of(根据某物实现出)。

当复合发生于应用域内的对象之间,表现出has-a的关系,当它发生于实现域内则表现is-implemented-in-terms-of的关系。

比较麻烦的是区分has-a和is-implemented-in-terms-of这两种对象关系。

假设你需要一个template,希望制造出一组class用来表现由不重复对象组成的set。

你的第一个直接是采用标准程序库提供的set template。

不幸的是,set的实现往往招致:每个元素耗用三个指针“的额外开销。因为set通常以平衡查找树实现而成,使它们在查找、安插、移除元素时保证拥有对数时间效率。当速度比空间重要,这是个通情达理的设计,但若你的程序是空间比速度重要呢?

那么标准程序库的set提供给你的是个错误决定下的取舍。似乎你还需写个自己的template。

实现set的方法有很多。其中一种便是在底层采用linked list。而标准程序库刚好有一个list template,于是你决定复用它。

更准确地说,你决定让你自己写的set template继承std::list。也就是让set<T>继承list<T>。

于是声明set template如下:

template<typename T>//将list应用于set,错误做法
class Set: public std::list<T>{/*...*/ };

上述代码是错误的。因为是public继承,所以应该表现is-a关系。但list可以内含重复元素,若数值3051被安插到list<int>两次,则list将内含两笔3051。但Set不可以内含重复元素,若数值3051被安插到lSet<int>两次,则Set将内含一笔3051。因此”Set是一种list“并不为真。

正确的做法是,你应当了解,Set对象可根据一个list对象实现出来:

template<typename T>//将list应用于set,正确做法
class Set{
public:
    bool member(const T& item) const;
    void insert(const T& item);
    void remove(const T& item);
    std::size_t size() const;
private:
    std::list<T> rep;//用来表述Set数据
};

Set成员函数可大量倚赖list及标准程序库其他部分提供的机能来完成,所以其实现很简单,只要你熟悉以STL编写程序。

总结

1.复合的意义与public继承完全不同。

2.在应用域,复合意味has-a。在实现域,复合意味is-implemented-in-terms-of。 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值