1,public继承分为两类:接口继承和实现继承.
这两种继承的差异类似于函数声明和函数继承的差异.
2,你的可能需求:
(1)希望只继承基类的接口;
(2)希望继承基类的接口和实现,而且可以改写它们.
(3)希望继承基类的接口和实现,但是不允许改写它们.
3,例子:
class Shape
{
public:
virtual void draw() const = 0;
virtual void error(const string& msg);
int objectID() const;
...
};
class Rectangle: public Shape { ... };
class Ellipse: public Shape { ... };
4,先看纯虚函数draw.
纯虚函数的两个突出特性:(1)它们必须被"继承了它们"的具体类重新声明;(2)它们在抽象类中通常没有定义.
那么可以得到:
声明一个纯虚函数的目的是为了让derived class只继承其接口.
注:但是我们可以为纯虚函数提供定义,你可以为Shape:draw供应一份实现代码.
如:
Shape *ps1 = new Rectangle; // fine
ps1->draw(); // calls Rectangle::draw
ps1->Shape::draw(); // 但是只能通过完整名称调用,虚基类无法生成对象.
5,再看一般的虚函数.
传统上会给出一份实现,derived class可以自行选择要不要加以改写(override).
声明一般虚函数的目的:
是为了让derived class继承该函数的接口和缺省行为.
6,看一个现实的例子:
class Airport { ... }; // represents airports
class Airplane
{
public:
virtual void fly(const Airport& destination);
...
};
void Airplane::fly(const Airport& destination)
{
default code for flying an airplane to
the given destination
}
class ModelA: public Airplane { ... };
class ModelB: public Airplane { ... };
fly缺省的行为同时被ModelA和ModelB继承,避免程序代码重复.
但是如果继续ModelC,可能导致:
"没有明白说我要"的情况下,ModelC继承了该缺省行为.
下面给出一个精巧的实现:
class Airplane //这里设为纯虚函数
{
public:
virtual void fly(const Airport& destination)=0;
...
};
void Airplane::fly(const Airport& destination)
{
default code for flying an airplane to
the given destination
}
//Derived class需要显式overridefly
class ModelA: public Airplane
{
virtual void fly(const Airport& destination)
{
Ariplane::fly(destination);
}
...
};
class ModelB: public Airplane
{
virtual void fly(const Airport& destination)
{
Ariplane::fly(destination);
}
...
};
class ModelC: public Airplane
{
virtual void fly(const Airport& destination)
{
自己的实现
}
...
};
7,声明非虚拟函数的目的:
为了令Derived class继承函数的接口和实现.
注:非虚拟函数代表的意义"不变形"凌驾于"变异性"之上,我们不应该在Derived class中重新定义它.
分享到:
相关推荐
条款36: 区分接口继承和实现继承 条款37: 决不要重新定义继承而来的非虚函数 条款38: 决不要重新定义继承而来的缺省参数值 条款39: 避免 "向下转换" 继承层次 条款40: 通过分层来体现 "有一个" 或 "用...来实现" ...
条款36:区分接口继承与实现继承 条款37:绝不要重新定义继承而来的非虚函数 条款38:绝不要重新定义继承而来的缺省参数值 条款39:避免向下转换继承层次 条款40:通过分层来体现有一个和用...来实现 条款41:区分继承和...
条款34:区分接口继承和实现继承 条款35:考虚virtual函数以外的其他选择 条款36:绝不重新定义继承而来的non-virtual函数 条款37:绝不重新定义继承而来的缺省参数值 条款38:通过复合塑模出has-a或“根据某物...
条款34:区分接口继承和实现继承 differentiate between inheritance of interface and inheritance of implementation. 条款35:考虑virtual函数以外的其他选择 consider alternatives to virtual functions. 条款...
条款36:内存管理——之二 179 条款37:auto_ptr 186 7 误区、陷阱以及错误的惯用法 201 条款38:对象标识 201 条款39:自动转换 204 条款40:对象的生存期——之一 206 条款41:对象的生存期——之二 209 8 ...
条款36: 用not1和remove_copy_if来表现copy_if 条款37: 用accumulate或for_each来统计序列 仿函数,仿函数类,函数等等 条款38: 把仿函数类设计成值传递的 条款39: 用纯函数做predicate 条款40: 增强仿函数类的...
条款36: 用not1和remove_copy_if来表现copy_if 条款37: 用accumulate或for_each来统计序列 仿函数,仿函数类,函数等等 条款38: 把仿函数类设计成值传递的 条款39: 用纯函数做predicate 条款40: 增强仿函数类的...
条款36:了解copy_if的正确实现 条款37:用accumulate或for_each来统计区间 仿函数、仿函数类、函数等 条款38:把仿函数类设计为用于值传递 条款39:用纯函数做判断式 条款40:使仿函数类可适配 条款41:了解...
提防在指针的容器上使用类似remove的算法 条款34:注意哪个算法需要有序区间 条款35:通过mismatch或lexicographical比较实现简单的忽略大小写字符串比较 条款36:了解copy_if的正确实现 条款37:用...
·条款二十四:理解虚拟函数、多继承、虚基类和RTTI所需的代价 ·条款二十五:将构造函数和非成员函数虚拟化 ·条款二十六:限制某个类所能产生的对象数量 ·条款二十七:要求或禁止在堆中产生对象 ...
条款25:将 constructor 和 non-member functions 虚化 123 Virtualizing constructors and non-member functions 条款26:限制某个 class 所能产生的对象数量 130 Limiting the number of objects of a class 条款...
ROHS豁免条款:ROHS豁免项清单及ROHS最新豁免条例.pdf
实现游戏开始界面中的我同意游戏条款功能
提高编程效率的50条建议 条款1:尽量用const和inline而不用#define 条款2:尽量用而不用 条款3:尽量用new和delete而不用malloc和free 内存管理的建议 设计与说明的建议 继承与面向对象的设计 杂项
公交服务采购的激励合同和质量条款:以智利圣地亚哥为例-word资料.pdf
1、P2P全推行情接口只是针对P2P实时传输编程技术和股票行情数据高压缩技术的学术研究之用,接口所提供的行情数据仅供技术分析爱好者学习交流和盘后复盘使用,接收者不得将行情数据用于任何商业盈利性应用。...
时间::单调 Perl 的单调递增时钟源 Time::Monotonic 允许访问各种平台(Mac OS X、Windows 和 ... 您可以根据与 Perl 本身相同的条款重新分发和/或修改它,Perl 版本 5.18.2 或您可以选择的任何更高版本的 Perl 5。
Content Containers..................................................................条款10: 当心allocator的协定和约束 条款11: 了解自定义allocator的正统使用法 条款12: 对STL容器的线程安全性的期待现实一些
云服务接口及协议文档,里面有手机寻回的设计,及与移动端的协议定义。
文件fred-package.lisp,fred-classes.lisp和fred.lisp共同实现了与圣路易斯联邦储备银行提供的美联储经济数据(FRED:registered:)API的Common Lisp接口。 此外,此版本还包含hist-date.lisp,它提供了表示和操作...