《Effective C++》学习笔记——条款38

本文探讨了面向对象设计中复合与继承的区别,重点介绍了复合在实现has-a与is-implemented-in-terms-of关系中的应用。通过具体的Person类和自定义Set类的例子,详细解释了如何利用复合来塑模不同类型的对象间的关系。


六、继承与面向对象设计


条款38、通过复合塑模出 has-a 或 “根据某物实现出”





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

  • public 继承 意味着 is-a 关系
  • 复合 意味着 has-a 或 is-implemented-in-terms-of
    • 当发生于应用域内的对象之间,表现出has-a关系
    • 当发生于实现域内则表现 is-implemented-in-terms-of

has-a

看一个person类

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

这里的Person类示范的是 has-a 关系。
很好理解,人有名字、地址、电话号码等。


is-implemented-in-terms-of

再一个例子,我们要创建一个 Set template,希望制造出一组class用来表现不重复对象组成的sets。
好像有现成的,标准程序库提供的 set template,但它在效率上不符合需求,所以决定用 list template,但是list可以包含重复的元素,又不符合需求,所以需要去改进它。
public 继承?
—— No! 这两个类之间并不是 is-a 关系,所以需要用到 复合

template<class T>
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;
};

template<typename T>
bool Set<T>::member(const T& item) const
{
    return std::find(rep.begin(), rep.end(), item) != rep.end();
}
template<typename T>
void Set<T>::insert(const T& item)
{
    if(!member(item))  rep.push_back(item);
}
template<typename T>
void Set<T>::remove(const T& item)
{
    typename std::list<T>iterator it = std::find(rep.begin(), rep.end(), item);
    if( it != rep.end() )  rep.erase(it);
}
template<typename T>
std::size_t Set<T>::size() const
{
    return rep.size();
}

这里的关系就不是 has-a,更不是 is-a,而是 is-implemented-in-terms-of


区分

实际上,区分is-a 和 has-a亦是容易的,难点在于 区分 has-a 与 is-implemented-in-terms-of
第一个例子,人有 名字、电话、地址等,应该也不会去理解成 根据名字来实现出人。
第二个例子,我要实现自己的Set类各种方法是根据list类来实现的,而非是因为 Set有一个什么方法。
再换一种思路,is-implemented-in-trems-of 的实现方法不止有复合,还有 private 继承(但是 推荐使用复合来解决),通过这也可以小区分一下。
关于private继承,将会在下一条款详述。


请记住
  • 复合 的意义与 public继承 完全不同。
  • 在应用域,复合意味着 has-a 关系;在 实现域, 复合意味着 is-implemented-in-trems-of 关系。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值