Chapter 7 Ad Hoc Polymorphism

来源:互联网 发布:软件测试论坛 编辑:程序博客网 时间:2024/06/01 10:47
Chapter 7 Ad Hoc Polymorphism
itseraoydhpCm7PHlcrpm ?7.1 ADT Conversions
?7.2 Overloading and Function
Selection
?7.3 Friend Functions
?7.4 Overloading Operators
?7.5 Unary Operator
Overloading
?7.6 Binary Operator
Overloading
?7.7 Overloading Assignment
and Subscripting Operators
?7.8 Polynomial: Type and
Language Expectations
?7.9 Overloading 1/0 Operators
<< and >>
?7.10 Overloading Operator ()
for Indexing
?7.11 Pointer Operators
?7.11 .1 Pointer to Class
Member
?7.12 Overloading new and
delete
?7.13 Pragmatics
?7.1 3.1 Signature Matching
?Summary
?Exercises
Chapter 7 Ad Hoc Polymorphism
itseraoydhpCm7PHlcrpm ?Polymorphism
P ol y m or ph i s m
is a means of giving
different meanings to the same message.
The meanings are dependent on the type of
data being processed.
?Conversion is the explicit or implicit change
of value between types. Conversions
provide a form of polymorphism.
Chapter 7 Ad Hoc Polymorphism
itseraoydhpCm7PHlcrpm ?The name has several interpretations that
depend on function selection. This is called
ad hoc polymorphism.
ad h oc pol y m or ph i s m .
This chapter
discusses overloading, especially operator
overloading, and conversions of data types.
?Operators are overloaded and selected based
on the signature matching algorithm.
?One principle of OOP is that user-defined
types must enjoy the same privileges as
native types.
7.1 ADT Conversions
?Explicit type conversion of an expression is
necessary when either the implicit
conversions are not desired or the
expression will not otherwise be legal.
?Explicit type conversion of an expression is
necessary when either the implicit
conversions are not desired or the
expression will not otherwise be legal.
7.1 ADT Conversions
my_string::my_string(const
tscrgoynm(:_char
*
p);
?This is automatically a type conversion
from char
*
to my_stri
itrym_ng
.
?Note that this use requires an overloaded
assignment operator.
7.1 ADT Conversions
?These are conversions from an already
defined type to a user-defined type.
?It is not possible for the user to add a
constructor to a built-in type.
?This can be done by defining a special
conversion function inside the class.
operator type()
{ .. . }
?Such a member function must be nonstatic.
?Demo on page 213: string7.cpp
7.1 ADT Conversions
?Notice that we did not simply return the
value of the private member s.
7.2 Overloading and Function
Selection
?Overloaded functions
O v e r l oade d f u n c t i on s
are an important
addition in C++. The overloaded meaning is
selected by matching the argument list of
the function call to the argument list of the
function declaration.
7.2 Overloading and Function
Selection
?The matching algorithm: Overloaded
Function Selection Algorithm
?1. Use an exact match if found.
?2. Try standard type promotions.
?3.
Try standard type conversions.
?4. Try user-defined conversions.
?5. Use a match to ellipsis if found.
?Standard promotions are better than other
standard conversions.
7.2 Overloading and Function
Selection
?Standard conversions also include pointer
conversions.
?An exact match is clearly best. Casts can be
used to force such a match.
?Demo on page 214: rational.cpp
?constructor converts
?member function converts from rational to
double
?three distinct function are overloaded
?match rule
7.3 Friend Functions
?The keyword friend
is a function specifier. It
gives a nonmember function access to the hidden
members of the class, and provides a method of
escaping the data hiding restrictions of C++.
?One reason for using friend
functions is that some
functions need privileged access to more than one
class. A
second reason is that friend
functions
pass all of their arguments through the argument
list, and each argument value is subject to
assignment-compatible conversions.
7.3 Friend Functions
?A friend
function must be declared inside
the class declaration to which it is a friend.
The function is prefaced by the keyword
friend,
and can appear in any part of the
class without affecting its meaning.
?Member functions of one class can be
friend
functions of another class.
7.3 Friend Functions
?If all member functions of one class are friend
functions of a second class, this can be specified
by writing friend class
classname
c l a s n a m e
.
.
7.3 Friend Functions
?Demo on page 218: matrix2.cpp
?friend function
7.3 Friend Functions
?The friend
function, however, straddles this
boundary. It has access to private members,
but is not itself a member function. It can be
used to provide quick fixes to code that
needs access to the implementation details
of a class.
?But the mechanism is easily abused.
7.4 Overloading Operators
?The keyword operator
is used to define a
type conversion member function. It is also
used to overload the built-in C++ operators.
?Overloading operators
O v e r l oadi n g ope r at or s
allows infix
expressions of both ADTs and built-in types
to be written. It is an important notational
convenience, and in many instances leads to
shorter and more readable programs.
7.4 Overloading Operators
?Unary and binary operators can be overloaded as
nonstatic member functions.
?Most unary operators can be overloaded as
ordinary functions, taking a single argument of
class or reference to class type.
?Most binary operators can be overloaded as
ordinary functions, taking one or both arguments
of class or reference to class type. The operators =,
(), [], and -> must be overloaded with a nonstatic
member function.
7.4 Overloading Operators
?Although meanings can be added to
operators, their associativity and precedence
remain the same.
7.4 Overloading Operators
?Almost all operators can be overloaded. The
exceptions are the member operator .
, the
member object selector operator .
.
*
*
, the
ternary conditional expression operator ? :
? :
,
the sizeof
s i z e of
operator, and the scope resolution
operator : :
:
. (See Section C.12.5, "Operator
Overloading," on page 449.)
7.4 Overloading Operators
?Available operators include all the arithmetic,
logical, comparison, equality, assignment, and bit
operators. Furthermore, the autoincrement and
autodecrement operators, ++ and --, can have
distinct prefix and postfix meanings. (See exercise
18, on page 251.) The subscript or index operator []
and the function call 0 can also be overloaded. The
class pointer operator -> and the member pointer
selector operator ->* can be overloaded. (See
exercise 19, on page 252.) It is also possible to
overload new and delete. The assignment, function
call, subscripting, and class pointer operators can
be overloaded only by nonstatic member functions.
7.4 Overloading Operators
?Demo on page 221: clock.cpp
7.5 Unary Operator Overloading
?Demo on page 221: clock.cpp
7.5 Unary Operator Overloading
?The constructor performs the usual
conversions from tot_secs to days, hours,
minutes, and seconds.
?The overloaded operator++() also updates
the implicit clock variable and returns the
updated value as well.
7.5 Unary Operator Overloading
7.5 Unary Operator Overloading
?It is also possible to overload prefix ++
using an ordinary function:
++c
is equivalent to c
.operator
++()
++c
is equivalent to operator++(c
)
7.6 Binary Operator Overloading
?This section shows how to overload binary
operators.
?When a binary operator is overloaded using
a member function, it has as its first
argument the implicitly passed class
variable, and as its second argument the
lone argument list parameter. Friend
functions and ordinary functions have both
arguments specified in the parameter list.
7.6 Binary Operator Overloading
?Demo on page 223: clock.cpp
?The integer expression is implicitly converted
to a clock by the conversion constructor clock: :
clock(unsigned long).
7.6 Binary Operator Overloading
?Demo on page 223: clock.cpp
?Remember that there is an implicit first
argument.
?The first argument of a member function that
overloads an operator must be of its class type.
7.6 Binary Operator Overloading
?Demo on page 223: clock.cpp
7.7 Overloading Assignment and
Subscripting Operators
?The assignment operator for a class type is by
default generated by the compiler to have
member-by-member assignment. This is fine when
shallow copying is suitable. For types, like
my_string and vect,
?The subscripting operator is usually overloaded
where a class type represents an aggregate for
which indexing is appropriate. The index
operation is expected to return a reference to an
element contained within the aggregate.
7.7 Overloading Assignment and
Subscripting Operators
?A constructor that converts an ordinary
integer array to a safe array will be added.
?Finally, the subscript operator is overloaded,
and replaces the member function element.
?Demo on page 226: vect2.h
?overloaded subscript operator
?element_type& operator[] (integral type) ;
?The following member function overloads
assignment for class vect:
7.7 Overloading Assignment and
Subscripting Operators
?operator=() function
?don抰 do anything if assignment is to the current
variable.
?guarantee the sizes
?p[] will be the left side.
7.7 Overloading Assignment and
Subscripting Operators
?Expressions of type vect can be evaluated
by overloading in appropriate ways the
various arithmetic operators.
7.7 Overloading Assignment and
Subscripting Operators
?Notice that overloading assignment and
overloading plus does not imply that
operator+= is overloaded.
?When overloading related sets of operators
it is customary to overload them
consistently.
7.7 Overloading Assignment and
Subscripting Operators
?Demo on page 229: string7.cpp
7.8 Polynomial: Type and Language
Expectations
?A type's behavior is largely dictated by
expectations found in the community that
uses it. So how a polynomial behaves is
determined by the mathematical
community's definitions. When we come to
write a polynomial type, we expect that the
basic mathematical operations, such as +, -,
*, and /, are available and work
appropriately.
7.8 Polynomial: Type and Language
Expectations
?A class provides a public interface that is
easy to use insofar as it meets both
expectations.
?Demo on page 230: poly2.cpp
7.9 Overloading 1/0 Operators <<
and >>
?In keeping with the spirit of OOP, it is
important to overload << to output userdefined
types as well as native types. The
operator << has two arguments, an
ostream& and the ADT, and it must
produce an ostream&.
7.9 Overloading 1/0 Operators <<
and >>
?Demo on page 231: rational.cpp
?When overloading the operator >> to produce
input to a user-defined type, the typical form is:
istream& operator>>(istream& p , user-defined
u s e r - d e f i n e d
type&
t y p e &
x)
7.9 Overloading I/O Operators <<
and >>
?Demo on page 231: rational.cpp
?If the function needs access to private members
of x, it must be made a friend of its class. A key
point is to make x a reference parameter so that
its value can be modified.
7.10 Overloading Operator () for
Indexing
?A matrix type that provides dynamically
allocated two-dimensional arrays can be
designed with the function call operator
overloaded to provide element selection.
?The function call operator () is overloadable
as a nonstatic member function.
?Demo on page 233: matrix3.cpp
7.11 Pointer Operators
?The structure pointer operator -> is
overloaded as a nonstatic class member
function.
?The overloaded structure pointer operator is
a unary operator on its left operand.
7.11 Pointer Operators
?It can return either a pointer to a class object,
an object of a class for which operator
-> is
defined, or a reference to a class for which
operator
-> is defined.
?Demo on page 236: triple.cpp
?Pointer to class object
7.11 .1 Pointer to Class Member
?A
pointer to class member is distinct from a
pointer to class. A
pointer to class member's
type is T: : *, where T is the class name.
C++ has two operators that act to
dereference a pointer to class member. The
pointer to member operators are:
.*
->*
7.11 .1 Pointer to Class Member
?Think of obj
obj
.
.
*
*
ptr-mem
pt r - m e m
and pointer->
poi n t e r - >
*
*
ptrpt
r -
mem
m e m
as first accessing the object and then
accessing and dereferencing the member
that is specified.
?Demo on page 237: showhide.cpp
?pointer to class member ( variable or function)
?pointer expression
7.11 .1 Pointer to Class Member
?Consider the memory layout for
representing an object. The object has a
base address and the various nonstatic
members are offset relative to this base
address. In effect, a pointer to class member
is used as an offset and is not a true pointer
n ot a t r u e poi n t e r
;
a true pointer has general memory addresses
as values. A static member is not offset and,
as such, a pointer to a static member is a
true address.
7.12 Overloading new and delete
?Most classes involve free store memory
allocation and deallocation. Sometimes
more sophisticated use of memory than is
provided by simple calls to operator new
and delete
is needed for efficiency or
robustness.
?Operator new
has the general form
::opt
new
placement
pl ac e m e n t
opt
type
t y pe
initializer
i n i t i al i z e r
opt
7.12 Overloading new and delete
: :new char [10]
; / / insist on global new
new(buff) X(a) ; / / call with buff using X: :X(a)
?Up to now we have been using the global
operator new() to allocate free store.
?The system provides a sizeof (type)
( t y pe )
argument to this function implicitly. Its
function prototype is
void* operator new(si ze-t size) ;
7.12 Overloading new and delete
?The operators new and delete can be overloaded.
?The class X has provided overloaded forms of
new() and delete(). When a class overloads
operator new(), the global operator is still
accessible using the scope resolution operator : : .
7.12 Overloading new and delete
?One reason to overload these operators is to
give them additional semantics, such as
providing diagnostic information or being
more fault tolerant. Also, the class can have
a more efficient memory allocation scheme
than that provided by the system.
7.12 Overloading new and delete
?The placement
pl ac e m e n t
syntax provides a commaseparated
argument list used to select an
overloaded operator new() with a matching
signature.
?This form of operator new uses the new.h
n e w . h
header file.
7.12 Overloading new and delete
?Demo on page 241: over_new.cpp
?delect operator comes in 2 flavors
?new.h file has the function pointer
_new_handler, which calls the error handler
for operator new.
?Demo on page 242: new_hadlr.cpp
7.13 Pragmatics
?Explicitly casting arguments can be both an
aid to documentation and a useful way to
avoid poorly understood conversion
sequences.
?Operator overloading is easily misused.
7.13 Pragmatics
?Generally speaking, overload symmetric
binary operators, such as +, *, ==, ! =, and
&&, with f
ri
end
functions. Both
arguments are then passed as ordinary
parameters. This subjects both arguments to
the same rules of parameter passing. Recall
that using a member function to provide
overloading for symmetric binary operators
causes the first argument to be passed via
the this
pointer.
7.13 Pragmatics
?Any time a class uses new to constructs
objects, it should provide an explicitly
overloaded operator=().
7.1 3.1 Signature Matching
?Signature matching rules are given in
simplified form in Section 7.2,
"Overloading and Function Selection," on
page 2 13. A further clarification of these
rules with examples is given in this section.
?For a given argument, a best match is
always an exact match. An exact match also
includes trivial conversions.
t r i v i al c on v e r s i on s .
7.1 3.1 Signature Matching
?The use of volatie is specialized. It means
that a variable can be modified external to
the program code.
7.1 3.1 Signature Matching
void print ( int i);
void print (const int & i);
?can be unambiguously overloaded.
?Demo on page 244: clock.cpp
?The call to reset (100) involves an argument match
between i n t and clock that is a user-defined
conversion invoking the constructor clock(unsigned).
?Where these
?conversions are unintended a new keyword expl i ci t
can be used in declaring the constructor to disable its
use as an implicit conversion.
Summary
?1. Overloading operators gives them new
meanings.
?2. There are four cast types in C++ :
?static-cast<type> (expression)
?reinterpret-cast< type>(expression)
?const-cast< type>(expression)
?dynami c-cast< type>(expression)
?3. A nonexplicit constructor of one argument is de
facto a type conversion from the argument's type
to the constructor's class type.
Summary
?4. The overloaded meaning is selected by
matching the argument list of the function call to
the argument list of the function declaration.
?Overloaded Function Selection Algorithm
?1. Use an exact match if found.
?2. Try standard type promotions.
?3.
Try standard type conversions.
?4. Try user-defined conversions.
?5. Use a match to ellipsis if found.
Summary
?5. The keyword friend is a function specifier that
allows a nonmember function access to the
nonpublic members of the class of which it is a
friend.
?6. The keyword operator is also used to overload
the built-in C++ operators.
?7. Operator overloading typically uses either
member functions or friend functions, because
both have privileged access.
?8.
An overloaded subscript operator can have any
return type and any argument list type.
class-name&
c l a s - n a m e &
operator [] (integral type)
原创粉丝点击