Classes in C++ C++ originally called "C with classes":

advertisement
Classes in C++
C++ originally called "C with classes":


Swedish connection: Bjarne Stoustrup borrowed from Simula (’67)
Simulating classes of real world objects
C++ continues to evolve:






Version 1.0 released by AT&T in 1986
Version 2.0 in 1990 (added multiple inheritance)
Version 3.0 in 1992 (templates)
ANSI standard in 1996 (exception handling, run time type info)
C++ became dominant OOPL in early 90's
Now Java and C# challenge
A class extends the C++ type system:
class Account { //creates a new type
}; //Note: you need this semi-colon in C++
Account a1,a2; //define variables of type Account
May 16
1
C structs
A data structure for dates in C:
struct Date {
int month, day, year;
};
int set(struct Date*, int m, int d, int y);
int print(struct Date*);
What’s the problem?
No information hiding



May 16
No way to control access to data (obscure side effects)
No way to prevent assigning an illegal value to month
Changing representation of Date breaks all client code
2
C++ structs
C++ provides for closer coupling of data and functions:
struct Date {
int month, day, year;
void set(int m, int d, int y);
void print(); //implement elsewhere
};
Invoke functions with variable . memberFunction():
Date today; //In C++, structs automatically define types
today.set(9,29,1953); today.print();
Now we have data abstraction:


Procedural abstraction hides details of code in functions
Data abstraction couples data structure and functions
Still, no information hiding: today.set(50,-10,0);
May 16
3
C++ adds class
C++ adds new keywords to support information hiding:
class Date {
int month, day, year;
public:
void set(int m, int d, int y);
void print(); //implement elsewhere
};
Members after public: are visible to clients:
Date today; today.print();
today.month = 50; //is this legal?

Members after class are by default private
May 16
4
Member functions
What can we add to Date to allow access to month?
class Date {
int month, day, year;
public:
void set(int m, int d, int y);
void print(); //implement elsewhere
int getMonth() { return month; }
};
cout << today.getMonth(); //outside class Date


Pros and cons of this approach?
inline function is efficient, though it tends to break information hiding
Let’s define set() and protects the month data:
void Date :: set(int m, int d, int y)
{ assert(m >= 1 && m <= 31);
month = m;
}
May 16
5
Inheritance
(class derivation)
class Account generalizes many kinds of bank
accounts: checking, savings, etc.
C++ class derivation captures this generation:
class Checking : public Account {
public:
Checking(float balance);
Checking(); //default constructor
};
: denotes derivation—Checking inherits from Account
public derivation denotes subtype inheritance

Account’s public methods accessible to instances of Checking
Checking myChecking(200);
myChecking.getBalance();
May 16
//Checking constructor
//Account function
6
OOP = Data abstraction
+ inheritance
+ dynamic binding
Polymorphism: a function can mean different things at runtime
Dynamic binding: defer function binding to a subtype until runtime
Suppose we want to draw a heterogeneous collection of shapes?
class Point { ... }; //a Point has x and y coordinates
class Shape {
protected: //accessible to subclasses but otherwise private
Point center; //all Shapes have a center Point
public:
Point where() { return center; }
virtual void move(Point to) //virtual can be overridden
{ center = to; draw(); } // by derived classes
virtual void draw()=0; //a "pure" virtual function
//draw() must be implemented by derived classes
//...
}
May 16
7
Subclasses override
virtual functions
class Triangle: public Shape {
Point sw, se, top; //Three points define triangle
public:
Triangle(Point a, Point b, Point c) : sw(a), se(b), top(c) {}
draw() //implementing pure virtual function
{ put_line(sw,top); //draw line from sw to top
put_line(top,se); //draw line from top to se
put_line(se,sw); //draw line from se to sw
}
};
class Circle : public Shape {
int radius;
public:
Circle(Point a, int r) : center(a), radius(r) {}
draw(); //draw a circle using center and radius
};
May 16
8
Calling a virtual function
{
//Construct some shapes
Shape aShape;
Circle c(Point(20,30),7);
//illegal--why?
//legal--what does it do?
//Create an array of various shapes
Shape* shapes[10];
//Why is this legal?
shapes[0] = new Circle(Point(20,30),7); //assign a Circle
shapes[1] = new Triangle(Point(50,50),Point(30,30),Point(40,40));
//... maybe assign other shapes, Rectangles, Squares, etc.
for (int i=0; i < 10; i++)
//draw all the shapes
shapes[i]->draw(); //each shape draws itself!
}
Why do we say that elements of shapes array are polymorphic?
How does polymorphic design support Open-Closed principle?
May 16
9
Why dynamic binding?
What kind of code does dynamic binding avoid?

Avoids lots of switch statements, e.g.:
switch (shapes[i]->isa)
//each Shape derived class has an isa data member
{ case(triangle) Triangle::draw(); //test enumeration
case(circle) Circle::draw(); //run specific draw()
// ...
}
Why is the dynamic binding version better for
big, growing programs?
May 16
10
Download