荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: Second (石开), 信区: Program
标  题: Part of C++ FAQ Lite[22]--继承(抽象基类)
发信站: 荔园晨风BBS站 (Thu Jun  7 05:52:33 2001), 转信

译文出处:东日文档   http://www.sunistudio.com/sunidoc.asp
[22] 继承 — 抽象基类
(part of c++ faq lite, copyright ? 1991-96, marshall cline, cline@parashift.
com)
----------------------------------------------------------------------------
----
faqs in section [22]:
[22.1] 将接口和实现分离的作用是什么?
[22.2] 在c++中如何分离接口和实现(就象 modula-2)?
[22.3] 什么是 abc?
[22.4] 什么是“纯虚”成员函数?
[22.5] 如何为包含指向(抽象)基类的指针的类定义拷贝构造函数或赋值操作符?
----------------------------------------------------------------------------
----
[22.1] 将接口和实现分离的作用是什么?
接口是公司最有价值的资源。设计接口比用一堆类来实现这个接口更费时间。而且接口

需要更昂贵的人力的时间。
既然接口如此有价值,它们应该被保护,以免因为数据结构和其他实现的改变而被破坏

因此,应该将接口和实现分离。
----------------------------------------------------------------------------
----
[22.2] 在c++中如何分离接口和实现(就象 modula-2)?
使用 abc。(译注:即抽象基类 abstract base class)
----------------------------------------------------------------------------
----
[22.3] 什么是 abc?
抽象基类(abstract base class).
在设计层次,抽象基类(abc)对应于抽象概念。如果你问一个机修工他是否修理交通工

具,他可能想知道你所说的是哪种交通工具。他不修理航天飞机、远洋轮、自行车或核

潜艇。问题在于“交通工具”是一个抽象概念(例如,除非你知道你要建造哪种交通工
具,
否则你无法建造一个“交通工具”)。在c++中,vehicle(交通工具)类是一个abc,而

bicycle,spaceshuttle等则是子类(ocernliner 是一种 vehicle)。在真实世界的oo
中,
abc无处不在。
在程序语言层次上,抽象基类(abc)是有一个或多个虚成员函数的类。无法建立抽象基

类的对象(实例)。
----------------------------------------------------------------------------
----
[22.4] 什么是“纯虚”成员函数?
将普通类变成抽象基类(也就是abc)的成员函数。通常只在派生类中实现它。
某些成员函数只在概念中存在;而没有合理的定义。例如,假设我让你在坐标(x, y)处

一个图形,大小为 7。你会问我:“我应该画哪种图形?”(圆,矩形,六边形等,画

都不同)。在c++中,我们必须指出 draw() 成员函数的实在物(由此用户才能在有一个

shape* 或者 shape& 的时候调用它),但我们认识到,在逻辑上,它只能在子类中被定
义:
    class shape {
    public:
      virtual void draw() const = 0;  // = 0 表示它是 "纯虚" 的
      // ...
    };
这个纯虚函数使 shape 成为了abc(抽象基类)。如果你愿意,你可以将“=0”语法看
作为
代码位于null指针处。因此 shape 向它的用户承诺了一个服务,然而 shape 无法提供
任何
代码来实现这个承诺。这样做使得即使基类没有足够的信息来实际定义成员函数时,也
强制
了任何由 shape 派生的具体类的对象给出成员函数。
注意,为纯虚函数提供一个实现是可能的,但是这样通常会使初学者糊涂,并且最好避
免这
样,直到熟练之后。
----------------------------------------------------------------------------
----
[22.5] 如何为包含指向(抽象)基类的指针的类定义拷贝构造函数或赋值操作符?
如果类拥有被(抽象)基类指针指向的对象,则在(抽象)基类中使用虚构造函数语法

就如同一般用法一样,在基类中声明一个纯虚方法 clone() :
    class shape {
    public:
      // ...
      virtual shape* clone() const = 0;   // 虚你(拷贝)构造函数
      // ...
    };
然后在每个派生类中实现 clone()方法:
    class circle {
    public:
      // ...
      virtual shape* clone() const { return new circle(*this); }
      // ...
    };
    class square {
    public:
      // ...
      virtual shape* clone() const { return new square(*this); }
      // ...
    };
现在假设每个 fred 对象有一个 shape 对象。fred对象自然不知道 shape是圆还是矩形
还是...
fred的拷贝构造函数和赋值操作符将调用shape的clone()方法来拷贝对象:
    class fred {
    public:
      fred(shape* p) : p_(p) { assert(p != null); }   // p 不能为 null
     ~fred() { delete p; }
      fred(const fred& f) : p_(f.p_->clone()) { }
      fred& operator= (const fred& f)
        {
          if (this != &f) {              // 检查自赋值
            shape* p2 = f.p_->clone();   // create new one first...
            delete p_;                   // ...then delete the old one
            p_ = p2;
          }
          return *this;
        }
      // ...
    private:
      shape* p_;
    };

--
                            既然热爱生命
                            那么,
                            一切都在意料之中。

※ 来源:·荔园晨风BBS站 bbs.szu.edu.cn·[FROM: 192.168.28.16]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店