Document 7143150
Download
Report
Transcript Document 7143150
OOP Class
Lawrence D’Antonio
Lecture 4
An Overview of C++, Part 2
What is a class?
A class is a set of objects sharing common
features.
A class defines an object’s attributes and
behavior. Methods are provided to act on
an object and to pass messages between
objects.
A class is the basic unit of abstraction.
A class is the basic unit of modularity.
A class can be concrete or abstract.
Class Design as Type Design
Scott Meyers, Item #19
How should objects of your new type be
created and destroyed?
How should object initialization differ from
object assignment?
What does it mean for objects of your new
type to be passed by value?
Class Design as Type Design 2
What are the restrictions on legal values
for your new type?
Does your new type fit into an inheritance
graph?
What kind of type conversions are allowed
for your new type?
What operators and functions make sense
for the new type?
Class Design as Type Design 3
What standard functions should be
disallowed?
Who should have access to members of
your new type?
What is the “undeclared interface” of your
new type?
How general is your new type?
Is a new type really what you need?
What is an object?
An object is an instance of a class.
An object has state, behavior, identity.
What is an object?
Coad-Yourdon
An abstraction of something in a problem
domain, reflecting the capabilities of the
system to keep information about it, interact
with it, or both; an encapsulation of attribute
values and their exclusive services.
What is an object?
OMG
An object is a thing. It is created as the
instance of an object type. Each object has
a unique identity that is distinct from and
independent of any of its characteristics.
Each object offers one or more operations.
What is an object?
Firesmith
An object is defined as a software abstraction that
models all relevant aspects of a single tangible or
conceptual entity or thing from the application
domain or solution space. An object is one of the
primary entities in an object-oriented application,
typically corresponds to a software module, and
consists of a set of related attribute types,
messages, exceptions, operations, and optional
component objects.
What is an object?
Booch
From the perspective of human cognition, an
object is any of the following:
A tangible and/or visible thing.
Something that may be apprehended
intellectually.
Something toward which thought or action is
directed.
What is an object?
Booch continued.
An object has state, behavior, and identity;
the structure and behavior of similar objects
are defined in their common class; the terms
instance and object are interchangeable.
What is an object?
Shlaer-Mellor
An object is an abstraction of a set of realworld things such that:
All the things in the set have the same
characteristic.
All instances are subject to and conform to
the same set of rules and policies.
What is an object?
Jacobson
An object is characterized by a number of
operations and a state which remembers the
effect of these operations.
What is encapsulation?
Internal details of objects are concealed
from the objects users (information hiding).
Both data and implementation may be
hidden. The object is a black box.
Access to members is controlled through
the class definition.
The accessible part of a class is called its
interface.
Data encapsulation example
class Clock {
private:
int hours; // 1-12 private
int minutes; // 0-59
public:
Clock(int h, int m) {
if (h < 1 || h > 12) {
throw(”Hours must be between 1 and
12″);
}
if (m < 0 || m > 59) {
throw(”Minutes must be between 0 and
59″);
}
h = hours;
m = minutes;
}
//...
};
Class Invariants
The above is an example of “Programming by
Contract.”
The class guarantees that
1 hours 12, 0 minutes 59
These are called class invariants
Data Members
Data members can be declared as:
const – a declaration that an object is read
only. The object may be stored in a CPU
register.
volatile – a declaration that an object’s
value may be changed asynchronously.
The object may not be stored in a CPU
register.
Data Members 2
static – A data member shared by all
objects of a class. There is only one copy
of a static member, it is not part of the
object memory layout.
mutable – A data member that is allowed
to be modified, even if it a member of a
const object.
Is the following code legal?
struct X {
static int a = 2;
};
main()
{
X my_x;
X::a = 4;
my_x::a = 5;
}
Not legal!
Cannot initialize static data member a
within class.
static variables are similar to extern
variables.
Is the following code legal?
struct X {
static int a;
};
main()
{
X my_x;
X::a = 4;
my_x::a = 5;
}
Not legal!
This is a linker error.
X::a was used but never defined.
Is the following code legal?
struct X {
static int a;
};
int X::a;
main()
{
X my_x;
X::a = 4;
my_x::a = 5;
}
Legal.
X::a was defined before being used.
Note: it is okay that X::a was not initialized.
Is the following code legal?
struct X {
static int a;
static const int b = 3;
};
int X::a = 2;
main()
{
X my_x;
X::a = 4;
my_x::a = X::b;
}
Legal.
static const members can be declared
and defined at the same time.
Is the following code legal?
void func(volatile std::list<int> li)
{
int n = li.front();
}
Not legal!
Only volatile member functions can be called on a volatile
object.
list::front() not a volatile function
What is a method?
A method is a member function that acts
upon an object. A method is generally
called for one object (exception: static
members).
Commonly found methods are
constructors, destructors, assignment,
mutators, accessors.
Static Members
#include <iostream>
using namespace std;
class X {
public:
int a;
void f(int b) { cout << “X::f()\n”;}
};
int main() {
int X::*ptiptr = &X::a; //pointer to data member
void (X::* ptfptr) (int) = &X::f; //pointer to member function
X xobject;
xobject.*ptiptr = 10;
(xobject.*ptfptr) (20);
}
What is message passing?
Messages are transfers of data or
requests for another object to take an
action.
Message passing example
Adapter pattern
What is polymorphism?
Different types of objects respond to the
same message and use the appropriate
method.
Parametric
Universal
Subtype
Polymorphism
Overloading
Ad-hoc
Coercion
Polymorphic Objects
A function (or operator) is polymorphic if it
has an argument that can accept different
types.
A variable is polymorphic if it can have
different types in different contexts.
A type is polymorphic if its operations can
apply to arguments of different types.
Overloading
The same name is used to denote
different functions.
These functions are distinguished by
different signatures.
Some languages (such as C++) allow the
programmer to define their own
overloaded functions and operators.
Overloading Example
int square(int x) { return x*x; }
long square(long x) { return x*x; }
float square(float x) { return x*x; }
double square(double x) { return x*x; }
Alternative Method
template<typename T>
T square(T x) { return x*x; }
This works on all data types for which operator * is
defined.
int x = square(4); //Calls square(int)
double y = square(4.2); //Calls square(double)
float z = square(3); //Calls square(int)
Implementation
How is overloading done?
Through name mangling. The compiler modifies
the names of each overloaded function.
Example
void foo(int,int);
void foo(double,double);
In Assembler, these would be renamed:
foo_Fii:
foo_Fdd:
Is this code legal?
#include <stdlib.h>
struct C1 {enum E {red, blue};};
struct C2 {enum E {red, blue};};
extern "C" int printf(const char *, ...);
void f(C1::E x) {printf("f(C1::E)\n");}
void f(C2::E x) {printf("f(C2::E)\n");}
int main() {
f(C1::red);
f(C2::red);
return EXIT_SUCCESS;
}
Yes, this is legal.
The nested enums C1::E and C2::E are
different types. So the overloaded functions
have different signatures.
Is this legal?
class X {
public:
int f();
double f();
};
No, you can’t overload only on return type.
Is this legal?
struct A {
static int f();
int f();
};
No, it’s not legal. You can’t overload by
static.
Is this legal?
typedef int I;
void f(float, int);
void f(float, I);
Not legal. A typedef of an int is still an
int.
Is this legal?
f(char*);
f(char[10]);
Not legal. The arguments are considered the
same type (pointer to char).
Is this legal?
g(char(*)[20]);
g(char(*)[40]);
Yes, it’s legal. You can distinguish
multidimensional arrays by their second (or
higher) dimensions.
Is this legal?
int f(int);
int f(const int);
Not legal. You can’t overload by constness
of argument.
Is this legal?
void f(int &) { std::cout << “int &\n”; }
void f(const int &) { std::cout << “const int &\n”;
}
main() {
f(3);
return 0;
}
Legal. const is used within a type specification.
Q: Which function is called?
A: f(const int &)
Is this legal?
void f(int) { std::cout << “int \n”; }
void f(int &) { std::cout << “int &\n”; }
main() {
f(3);
return 0;
}
Legal. The signatures are different.
Q: Which function is called?
A: f(int)
Is this legal?
void f(double int) { std::cout << “double \n”; }
void f(const int &) { std::cout << “const int &\n”;
}
main() {
f(3);
return 0;
}
Legal. The signatures are different.
Q: Which function is called?
A: f(const int &)
Is this legal?
void f(int);
void f(int i = 10);
Not legal. Can’t overload by default
arguments.
Is this legal?
void g(int (float));
void g(int (*)(float));
Not legal. Both functions take the same
argument (pointer to function of the same
type).
Coercion
A coercion is an implicit type conversion.
This allows the programmer to omit a type
cast.
There are three types of coercions:
Compiler defined (such as promotions,
derived base)
Constructor
User defined
Compiler defined coercions
Simple example
double x;
x = 2; //2 promoted to double
Function call coercions
void foo(double x) { //... }
//foo() can be called with any type that can be
//converted to double
foo((short) 4);
foo(‘a’);
foo(3L);
foo(2.3F);
Is this legal?
#include <iostream>
void f(char a, int b)
{ std::cout << a << b << '\n'; }
void f(int a, char b)
{ std::cout << a << b << '\n'; }
main()
{
f('a','b');
return 0;
}
Not legal, it’s ambiguous.
Coercion vs. Overloading example
3 +
3 +
3.0
3.0
4;
4.0;
+ 4;
+ 4.0;
How does this work?
Explanations of example
Four overloaded versions of operator +
Two overloaded versions of operator +,
one for integers, the other for doubles. The
middle two calls in the example would use
coercion.
One version of operator +, for doubles.
The first three calls in the example would
use coercion.
Derived to Base Conversion
C++ will implicitly convert a pointer or
reference to a derived class to a pointer or
reference to the base class. This is
because the derived class has a copy of
the base class inside it.
A pointer to the base class cannot be
converted to a pointer to the derived class.
Is this legal?
class A {};
class B: public A {};
class C: protected A {};
class D: private A {};
main() {
A *pa = new B;
pa = new C;
pa = new D;
return 0;
}
pa = new B; //Legal, B is an A
pa = new C; //Illegal, C is not an A
pa = new D; //Illegal, D is not an A
In the last two cases, the base class is
inaccessible.
Is this legal?
class A {};
class C: protected A {
public:
void foo() { A *pa = this; }
};
class D: private A {
public:
void foo() { A *pa = this; }
};
main() {
C c;
c.foo();
D d;
d.foo();
return 0;
}
Yes, it’s legal. Protected and private
inheritance exemplify a has-a relationship,
rather than an is-a relationship. Member
functions are allowed to convert pointer to
derived into pointer to base.
Pointer to Member Conversions
What is the relationship between a pointer
to member of a base class and a derived
class?
Is this legal?
struct A {
int a;
};
struct B: public A {
int a;
};
main()
{
A a;
B b;
int A::*pa = &B::a;
int B::*pb = &A::a;
return 0;
}
Complicated.
int A::*pa = &B::a;
is illegal. Can’t convert pointer to derived
member to a pointer to base member.
int B::*pb = &A::a;
Is legal. Can convert pointer to base member to
a pointer to derived member.
Conversion Constructors
Constructors that take a single argument
can be thought of as a type conversion.
struct X { X(int); };
So that any code that expects an object of
class X can be passed an int that will
then be converted to an X.
Is this legal?
struct X { X(int){} };
void f(const X &) {}
void g(int) {}
void g(X) {}
main() {
f(3);
g(4);
g(X(5));
return 0;
}
f(3); //Legal, you can create a temp
//object X(3), which is passed to
//f()
g(4); //Legal, calls g(int)
g(X(5)); //Legal, calls g(X)
Is this legal?
struct X { X(int){} };
void f(X &) {}
void g(int) {}
void g(X) {}
main() {
int a = 2;
f(3);
f(a);
g(4);
g(X(5));
return 0;
}
f(3);
//Not legal, can’t use temp X object to initialize an X &
f(a);
//Not legal, can’t use temp X object to initialize an X &
g(4); //Legal, as before
g(X(5)); //Legal, as before
Is this legal?
struct X { X(int){} };
struct Y { Y(X) {} };
void f(Y) {}
main() {
f(3);
return 0;
}
Not legal.
Basically, only one level conversions are
allowed. Not allowed to convert int to X to Y.
Is this legal?
struct X { X(int){} };
void f(X) {}
void g(int) {}
void g(X) {}
main() {
int a = 2;
f(3);
f(a);
g(4);
g(X(5));
return 0;
}
f(3); //Legal, temp X is passed by value
f(a); //Legal, temp X is passed by value
g(4); //Legal, as before
g(X(5)); //Legal, as before
Parametric Polymorphism
Parametric polymorphism parametrizes
the object type (e.g., a list class, where the
type of object stored is parametrized).
Template Functions
template<class T>
T max(T a, T b) {
return a > b ? a : b;
}
Is this legal?
int a,b = 6;
const int c = 3;
double x,y = 3.2;
a
a
x
x
=
=
=
=
max(b,4);
max(b,c);
max(y,3.3);
max(b,y);
a
a
x
x
=
=
=
=
max(b,4); //Legal, max<int,int>
max(b,c); //Legal, max<int,int>
max(y,3.3); //Legal, max<double,double>
max(b,y); //Illegal, no max<int,double>
A template function is called only when there is an exact
match for type parameters (only trivial conversions, such
as const int to int are allowed).
Better max?
template<class S, class T>
T max(S a, T b) {
return a > b ? a : b;
}
main() {
int a, b = 3;
double x, y = 3.2;
a
x
x
x
=
=
=
=
max(b,5);
max(y,5.4);
max(b,y);
max(y,b);
return 0;
}
a = max(b,5);
//Legal, returns 5
x = max(y,5.4);
//Legal, returns 5.4
x = max(b,y);
//Legal, 3.2
x = max(y,b);
//Legal, but
//returns 3.0!
Best max?
template<class R, class S, class T>
R max(S a, T b) {
return a > b ? a : b;
}
main() {
int a, b = 3;
double x, y = 3.2;
a
x
x
x
=
=
=
=
max(b,5);
max(y,5.4);
max(b,y);
max(y,b);
return 0;
}
Doesn’t compile. The function max() is
supposed to have 3 template parameters.
But each call only uses 2 parameters.
Try this max
template<class R, class S, class T>
R max(S a, T b) {
return a > b ? a : b;
}
main() {
int a, b = 3;
double x, y = 3.2;
a
x
x
x
=
=
=
=
max<int>(b,5);
max<double>(y,5.4);
max<double>(b,y);
max<double>(y,b);
return 0;
}
Subtype polymorphism
Subtype (or inclusion) polymorphism
allows objects of a given type to be
substituted for by objects of a subtype.
What is inheritance?
One class (derived/child) relies on the
definition of another class (base/parent).
Single vs. multiple inheritance
A method of sharing code or sharing
interface among classes.
Language may define a class tree (with
single root): Java, Smalltalk
Language may define a class forest: C++
What is typing?
Static typing: Data type determined at
compile-time. Type must be declared.
Dynamic typing: Data type may be
determined at run-time. Type need not be
declared.
Strong typing: Variables are bound to a
specific type.
Weak typing: A variable’s type may
change.
Varieties of typing
Static and strong typing: Java, Pascal,
OCaml, Haskell
Static and weak typing: C/C++
Dynamic and strong typing: Python
Dynamic and weak typing: PHP
Dynamic typing example
# Python example
class Cat: def speak(self): print "meow!"
class Dog: def speak(self): print "woof!"
class Bob: def speak(self): print "hello world!"
def command(pet): pet.speak()
pets = [ Cat(), Dog(), Bob() ]
for pet in pets:
command(pet)
Weak typing example
var x := 5;
var y := "37";
Print(x + y);
In Visual Basic this prints: 42
In JavaScript this prints: 537
What is exception handling?
The mechanism used to report and
recover from abnormal states.
When an error is detected, execution is
passed to a handler.