没有合适的资源?快使用搜索试试~ 我知道了~
首页C++ Common Knowledge : Essential Intermediate Programming
C++ Common Knowledge : Essential Intermediate Programming
4星 · 超过85%的资源 需积分: 9 27 下载量 156 浏览量
更新于2023-03-03
评论
收藏 1.38MB PDF 举报
C++ Common Knowledge : Essential Intermediate Programming
资源详情
资源评论
资源推荐
Item 1. Data Abstraction
A ―type‖ is a set of operations, and an ―abstract data type‖ is a set of operations
with an implementation. When we identify objects in a problem domain, the first
question we should ask about them is, ―What can I do with this object?‖ not
―How is this object implemented?‖ Therefore, if a natural description of a
problem involves employees, contracts, and payroll records, then the
programming language used to solve the problem should contain Employee,
Contract, and PayrollRecord types. This allows an efficient, two-way
translation between the problem domain and the solution domain, and software
written this way has less ―translation noise‖ and is simpler and more correct.
In a general-purpose programming language like C++, we don’t have
application-specific types like Employee. Instead, we have something better:
the language facilities to create sophisticated abstract data types. The purpose
of an abstract data type is, essentially, to extend the programming language
into a particular problem domain.
No universally accepted procedure exists for designing abstract data types in
C++. This aspect of programming still has its share of inspiration and artistry,
but most successful approaches follow a set of similar steps.
1.
Choose a descriptive name for the type. If you have trouble choosing a name for the
type, you don’t know enough about what you want to implement. Go think some
more. An abstract data type should represent a single, well-defined concept, and
the name for that concept should be obvious.
2.
List the operations that the type can perform. An abstract data type is defined by
what you can do with it. Remember initialization (constructors), cleanup
(destructor), copying (copy operations), and conversions (nonexplicit
single-argument constructors and conversion operators). Never, ever, simply
provide a bunch of get/set operations on the data members of the implementation.
That’s not data abstraction; that’s laziness and lack of imagination.
3.
Design an interface for the type. The type should be, as Scott Meyers tells us, ―easy
to use correctly and hard to use incorrectly.‖ An abstract data type extends the
language; do proper language design. Put yourself in the place of the user of your
type, and write some code with your interface. Proper interface design is as much a
question of psychology and empathy as technical prowess.
4.
Implement the type. Don’t let the implementation affect the interface of the type.
Implement the contract promised by the type’s interface. Remember that the
implementations of most abstract data types will change much more frequently than
their interfaces.
Item 2. Polymorphism
The topic of polymorphism is given mystical status in some programming texts
and is ignored in others, but it’s a simple, useful concept that the C++ language
supports. According to the standard, a ―polymorphic type‖ is a class type that
has a virtual function. From the design perspective, a ―polymorphic object‖ is an
object with more than one type, and a ―polymorphic base class‖ is a base class
that is designed for use by polymorphic objects.
Consider a type of financial option, AmOption, as shown in Figure 1.
Figure 1. Polymorphic leveraging in a financial option hierarchy. An
American option has four types.
An AmOption object has four types: It is simultaneously an AmOption, an Option,
a Deal, and a Priceable. Because a type is a set of operations (see Data
Abstraction [1, 1] and Capability Queries [27, 93]), an AmOption object can
be manipulated through any one of its four interfaces. This means that an
AmOption object can be manipulated by code that is written to the Deal,
Priceable, and Option interfaces, thereby allowing the implementation of
AmOption to leverage and reuse all that code. For a polymorphic type such as
AmOption, the most important things inherited from its base classes are their
interfaces, not their implementations. In fact, it’s not uncommon, and is often
desirable, for a base class to consist of nothing but interface (see Capability
Queries [27, 93]).
Of course, there’s a catch. For this leveraging to work, a properly designed
polymorphic class must be substitutable for each of its base classes. In other
words, if generic code written to the Option interface gets an AmOption object,
that object had better behave like an Option!
This is not to say that an AmOption should behave identically to an Option. (For
one thing, it may be the case that many of the Option base class’s operations
are pure virtual functions with no implementation.) Rather, it’s profitable to
think of a polymorphic base class like Option as a contract. The base class
makes certain promises to users of its interface; these include firm syntactic
promises that certain member functions can be called with certain types of
arguments and less easily verifiable semantic promises concerning what will
actually occur when a particular member function is called. Concrete derived
classes like AmOption and EurOption are subcontractors that implement the
contract Option has established with its clients, as shown in Figure 2.
Figure 2. A polymorphic contractor and its subcontractors. The
Option base class specifies a contract.
[View full size image]
For example, if Option has a pure virtual price member function that gives the
present value of the Option, both AmOption and EurOption must implement
this function. It obviously won’t implement identical behavior for these two
types of Option, but it should calculate and return a price, not make a telephone
call or print a file.
On the other hand, if I were to call the price function of two different interfaces
to the same object, I’d better get the same result. Essentially, either call should
bind to the same function:
AmOption *d = new AmOption;
Option *b = d;
d->price(); // if this calls AmOption::price...
b->price(); // ...so should this!
This makes sense. (It’s surprising how much of advanced object-oriented
programming is basic common sense surrounded by impenetrable syntax.) If I
were to ask you, ―What’s the present value of that American option?‖ I’d expect
to receive the same answer if I’d phrased my question as, ―What’s the present
value of that option?‖
The same reasoning applies, of course, to an object’s nonvirtual functions:
b->update(); // if this calls Option::update...
d->update(); // ...so should this!
The contract provided by the base class is what allows the ―polymorphic‖ code
written to the base class interface to work with specific options while promoting
healthful ignorance of their existence. In other words, the polymorphic code
may be manipulating AmOption and EurOption objects, but as far as it’s
concerned they’re all just Options. Various concrete Option types can be added
and removed without affecting the generic code that is aware only of the Option
base class. If an AsianOption shows up at some point, the polymorphic code
that knows only about Options will be able to manipulate it in blissful ignorance
of its specific type, and if it should later disappear, it won’t be missed.
By the same token, concrete option types such as AmOption and EurOption
need to be aware only of the base classes whose contracts they implement and
are independent of changes to the generic code. In principle, the base class can
be ignorant of everything but itself. From a practical perspective, the design of
its interface will take into account the requirements of its anticipated users, and
it should be designed in such a way that derived classes can easily deduce and
implement its contract (see Template Method [22, 77]). However, a base
class should have no specific knowledge of any of the classes derived from it,
because such knowledge inevitably makes it difficult to add or remove derived
classes in the hierarchy.
In object-oriented design, as in life, ignorance is bliss (see also Virtual
Constructors and Prototype [29, 99] and Factory Method [30, 103]).
Item 3. Design Patterns
Anyone who is not already familiar with design patterns may, after a brief
survey of the field, come away with the impression that design patterns are a lot
of marketing hype, are just some simple coding techniques, or are the
playthings of computer scientists who really should get out more. While each of
these impressions carries a grain of truth, design patterns are an essential
component of the professional C++ programmer’s toolkit.
A ―design pattern‖ is a recurring architectural theme that provides a solution to
a common design problem within a particular context and describes the
consequences of this solution. A design pattern is more than a simple
description of a technique; it’s a named capsule of design wisdom gleaned from
successful existing practice, written in such a way that it can be easily
communicated and reused. Patterns are about programmer to programmer
communication.
From a practical perspective, design patterns have two important properties.
First, they describe proven, successful design techniques that can be
customized in a context-dependent way to new design situations. Second, and
perhaps more important, mentioning the application of a particular pattern
serves to document not only the technique that is applied but also the reasons
for its application and the effect of having applied it.
This sort of thing is nothing new. Consider an analogy from the field of
algorithms. (Algorithms are not design patterns, and they’re not ―code patterns.‖
They’re algorithms, and this is an analogy.) Consider the following statement
that I might make to a colleague: ―I have an unsorted sequence that I have to
search a number of times. Therefore, I’m going to quick sort it and use binary
search to perform each lookup.‖ The ability to use the terms ―quick sort‖ and
―binary search‖ is of inestimable value not only in design but also in
communicating that design to an educated colleague. When I say ―quick sort,‖
my colleague knows that the sequence I’m sorting is in a random access
structure, that it will probably be sorted within O(nlg
2
n) time, and that the
elements in the sequence may be compared with a less-than-like operator.
When I say ―binary search,‖ my colleague knows (even if I hadn’t earlier
mentioned ―quick sort‖) that the sequence is sorted, that I will locate the item of
interest within O(lg
2
n) comparisons, and that an appropriate operation is
available to compare sequence elements. Shared knowledge of, and a standard
vocabulary for, standard algorithms permits not only efficient documentation
but also efficient criticism. For example, if I planned to perform this search and
sort procedure on a singly linked list structure, my colleague would immediately
smirk and point out that I couldn’t use quick sort and probably wouldn’t want to
use binary search.
Until the advent of design patterns, we missed these advantages in
documentation, communication, and efficient smirking with our object-oriented
designs. We were forced into low-level descriptions of our designs, with all the
inefficiency and imprecision that entails. It’s not that techniques for
sophisticated object-oriented design didn’t exist; it’s that the techniques were
not readily available to the entire programming community under a shared,
common terminology. Design patterns address that problem, and we can now
describe object-oriented designs as efficiently and unambiguously as
algorithmic designs.
For example, when we see that the Bridge pattern has been applied to a design,
we know that at a simple mechanical level an abstract data type implementation
剩余152页未读,继续阅读
louisla
- 粉丝: 7
- 资源: 1
上传资源 快速赚钱
- 我的内容管理 收起
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
会员权益专享
最新资源
- 27页智慧街道信息化建设综合解决方案.pptx
- 计算机二级Ms-Office选择题汇总.doc
- 单链表的插入和删除实验报告 (2).docx
- 单链表的插入和删除实验报告.pdf
- 物联网智能终端项目设备管理方案.pdf
- 如何打造品牌的模式.doc
- 样式控制与页面布局.pdf
- 武汉理工Java实验报告(二).docx
- 2021线上新品消费趋势报告.pdf
- 第3章 Matlab中的矩阵及其运算.docx
- 基于Web的人力资源管理系统的必要性和可行性.doc
- 基于一阶倒立摆的matlab仿真实验.doc
- 速运公司物流管理模式研究教材
- 大数据与管理.pptx
- 单片机课程设计之步进电机.doc
- 大数据与数据挖掘.pptx
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论2