C++ Classes - bhecker.com
Download
Report
Transcript C++ Classes - bhecker.com
C++ Classes
How to Create and Use Them
Overview
•
•
•
•
Terminology
File Topology
Designing Classes
Functions in Classes (methods)
Constructor
Accessors/Modifiers
Miscellaneous
• The Driver and Object instantiation
2
Terminology
•
•
•
•
•
•
•
Now in OO land (Object-Oriented) – Real C++ programming!
A class is just a combination of data and functions
It creates a new data type!
A class is a generic description
Create several instances of this class (objects)
Each instance has their own variables (they don’t share)
Functions are now called methods or behaviors (and rarely member
functions)
3
File Topology
(separate files for everything)
Cat.cpp
Dog.cpp
Description
of a cat
Description
of a dog
Driver.cpp
This is where we create
instances of dog and cats
and then tell them what
to do. It’s the controlling
algorithm
Person.cpp
Description
of a person
4
A couple of rules
Classes usually begin with an upper-case letter
The name of the file that you put the class in should be called the
<class name>.cpp
Especially if it’s a public class (later)
Example:
If we are creating a dog, we should name the class
Dog and put it into a file named Dog.cpp
Remember, C++ is case-sensitive!
5
The Smallest Class
Has template:
class <class name> {
};
Example: you’re told to create class X
Solution:
class X {
};
Remember, this should go in a separate file named X.cpp (not x.cpp)
6
A “real life” example
The CDog
Attributes (characteristics)
rabid or not rabid (bool)
weight (int or float)
name (char [ ])
Behaviors
growl
eat
7
Step 1: The Skeleton
class CDog {
// attributes will go here – name, weight, rabid
// behaviors will go here – growl, eat
};
8
Step 2: The attributes
(we’ll discuss public later)
class CDog {
public:
boolean rabid;
int weight;
char name[255];
// Behaviors go here
};
9
Step 3: The Constructor
This is a special function
Used to give initial values to ALL attributes
Is activated when someone creates a new instance
of the class
The name of this function MUST be the same name as the class
10
Step 3: Designing the Constructor
Constructors will vary, depending on design
Ask questions:
Are all CDogs born either rabid or non-rabid?
(yes – they are all born non-rabid)
Are all CDogs born with the same weight?
(no – they are born with different weights)
Are all CDogs born with the same name?
(no – they all have different names)
If ever “no”, then you need information passed in as parameters.
11
Step 3: The Constructor
class CDog {
public:
boolean rabidOrNot;
int weight;
char name [255];
// Constructor
CDog::CDog (int x, String y) {
rabid = false;
weight = x;
strcpy (name, y);
}
// Behaviors go here
};
Notice that every
CDog we create
will be born
non-rabid. The
weight and name
will depend on
the
values of the
parameters
12
The Driver
We’re talking about a whole new file!
The Driver contains main()
It’s the controlling algorithm
Steps:
Type in the skeleton
Create a couple of instances of classes
Start telling them what to do
13
Step 1: Type in the Skeleton
#include <iostream.h>
void main ( ) {
// Create your instances here!
}
14
Step 2: Declare A CDog Pointer
#include <iostream.h>
void main ( ) {
CDog* c1;
}
// null means “dead”
null
c1
15
The new operator
new
Brings instances “to life”
Calls the class’ constructor
Opens up enough space in memory to fit an instance of
that class
Format:
<class>* <var_name>;
<var_name> = new <class> (<parameters>);
16
Step 3: Bring c1 to Life
#include <iostream.h>
void main ( ) {
CDog* c1;
c1 = new CDog (14, “Bob”);
}
null
c1
new calls the CDog’s constructor
CDog::CDog (int x, char y[ ]) {
rabid = false;
weight = x;
strcpy (name, y);
}
17
Opens Space
#include <iostream.h>
void main ( ) {
CDog* c1;
c1 = new CDog (14, “Bob”);
}
null
c1
new calls the CDog’s constructor
CDog::CDog (int x, char y[ ]) {
rabid = false;
weight = x;
strcpy (name, y);
}
18
Data Passing
#include <iostream.h>
void main ( ) {
CDog* c1;
c1 = new CDog (14, “Bob”);
}
null
c1
// This is over in CDog.cpp
CDog::CDog (int x, char y[ ]) {
rabid = false;
weight = x;
strcpy (name, y);
}
19
Data Passing
#include <iostream.h>
void main ( ) {
CDog* c1;
c1 = new CDog (14, “Bob”);
}
null
c1
// This is over in CDog.cpp
CDog::CDog (int x, char y[ ]) {
rabid = false;
weight = x;
strcpy (name, y);
}
rabid:false
weight:14
name:”bob”
20
Declare a 2nd CDog
#include <iostream.h>
void main ( ) {
CDog* c1;
c1 = new CDog (14, “Bob”);
CDog c2 (7, “Ethel”);
}
// This is over in CDog.cpp
CDog::CDog (int x, char y[ ]) {
rabid = false;
weight = x;
strcpy (name, y);
}
null
c1
rabid:false
weight:14
name:”bob”
21
Opens Space
#include <iostream.h>
void main ( ) {
CDog* c1;
c1 = new CDog (14, “Bob”);
CDog c2 (7, “Ethel”);
}
null
c1
// This is over in CDog.cpp
CDog::CDog (int x, char y[ ]) {
rabid = false;
weight = x;
strcpy (name, y);
}
c2
rabid:false
weight:14
name:”bob”
22
Data Passing
#include <iostream.h>
void main ( ) {
CDog* c1;
c1 = new CDog (14, “Bob”);
CDog c2 (7, “Ethel”);
}
null
c1
c2
// This is over in CDog.cpp
CDog::CDog (int x, char y[ ]) {
rabid = false;
weight = x;
strcpy (name, y);
}
rabid:false
weight:14
name:”bob”
23
Copy Values to Memory
#include <iostream.h>
void main ( ) {
CDog* c1;
c1 = new CDog (14, “Bob”);
CDog c2 (7, “Ethel”);
}
null
c1
c2
// This is over in CDog.cpp
CDog::CDog (int x, char y[ ]) {
rabid = false;
weight = x;
strcpy (name, y);
}
rabid:false
rabid:false
weight:14
weight:7
name:”bob”
name:”Ethel”
24
Back to CDog
class CDog {
public:
boolean rabidOrNot;
int weight;
char name [255];
// Constructor
CDog::CDog (int x, char y[ ]) {
rabid = false;
weight = x;
strcpy (name, y);
}
// Behaviors we still need to eat and growl
};
25
Miscellaneous Methods
Follow the pattern
void CDog::eat ( ) {
cout << name << “ is now eating” << endl;
weight++;
}
void CDog::growl ( ) {
cout << “Grrrr” << endl;
}
26
Add Methods
class CDog {
public:
boolean rabidOrNot;
int weight;
char name [255];
// Constructor
CDog::CDog (int x, char y[ ]) {
rabid = false;
weight = x;
strcpy (name, y);
}
void CDog::eat ( ) {
cout << name << “ is now eating” << endl;
weight++;
}
void CDog::growl ( ) {
cout << “Grrrr” << endl;
}
};
27
The “.” and “->” operators
“Dot” operator used for non-pointers to:
Get to an instances attributes
Get to an instances methods
Basically get inside the instance
Format:
<instance>.<attribute or method>
Arrow operator used for pointers
Format:
<instance> -> <attribute or method>
28
Using the “.” and “->” Operators
#include <iostream.h>
void main ( ) {
CDog* c1;
c1 = new CDog (14, “Bob”);
CDog c2 (7, “Ethel”);
c2.bark( );
c1->growl( );
}
29
Accessors and Modifiers
Accessors
A method that returns the value of an attribute
Will have non-void return type
Has return statement inside
Modifiers
A method that changes the value of an attribute
Change is based off of a parameter value
Has a void return type
Have one accessor and one modifier per attribute
30
Accessors and Modifiers
Accessor for the rabid attribute
bool CDog::getRabid ( ) {
return rabid;
}
Modifier for the rabid attribute
void CDog::setRabid (bool myBoolean) {
rabid = myBoolean;
}
Put these inside of the CDog class
31
Using accessors and modifiers
#include <iostream.h>
void main ( ) {
CDog* c1;
c1 = new CDog (14, “Bob”);
CDog c2 (7, “Ethel”);
c1->setRabid (1);
// prints 1 for true
cout << c1->getRabid( ) << endl;
}
32
Make a Separate Header File
(for the generic description)
class CDog {
public:
int weight;
bool rabid;
char name [ ];
CDog (int x, char y[ ]);
bool getRabid ( );
void setRabid (bool x);
char [ ] getName ( );
void setName (char z[ ]);
int getWeight ( );
void setWeight (int x);
void bark( );
void growl( );
};
33
Our Final CDog.cpp
Cdog.cpp
#include <iostream.h>
#include <CDog.h>
// Constructor
CDog::CDog (int x, char y[ ]) {
rabid = false;
weight = x;
strcpy(name, y);
}
void CDog::eat ( ) {
cout << name << “ is eating”;
}
void CDog::growl ( ) {
cout << “Grrrr”;
}
Cdog.h
bool CDog::getRabid ( ) {
return rabid;
}
void CDog::setRabid (bool x) {
rabid = x;
}
int CDog::getWeight ( ) {
return weight;
}
void CDog::setWeight (int y) {
weight = y;
}
char[ ] CDog::getName ( ) {
return name;
}
void setName (char z[ ]) {
name = z;
}
34
Summary of Class Concepts
A class is a generic description which may have many instances
When creating classes
1. Sketch the skeleton
2. Fill in the attributes
3. Make the constructor
4. Make the accessors/modifiers/miscellaneous
Classes go in separate files
The “.” and “->” operators tell the instances which method to run
35
Inheritance and Objects
Inheritance
• Inheritance allows one class to take on the properties
of another
• Superclass-subclass relationship
• Sometimes called parent-child relationship
• Use the : <class name> to express this relationship
• Subclass will “inherit” certain attributes and methods
• Benefit: good design, reuse of code
37
Class Hierarchy
Mammal
int weight
giveBirth( )
Land-Mammal
int numLegs
Dog
boolean rabid
Chihuahua
Question: how many
attributes does Dog
have?
SheepDog
38
Things to Note
• Land-Mammal is a superclass to Dog, but a
subclass to Mammal
• Dog has three attributes
weight, numLegs and rabid
Two from inheritance, one it declared itself
39
An Example
(CDog.h – just review)
#include <iostream.h>
#include <string.h>
class CDog {
public:
int weight;
char name [255];
bool rabid;
CDog(int x);
void growl( );
};
40
CDog.cpp
(still review)
#include "CDog.h"
CDog::CDog(int x) {
weight = x;
rabid = false;
strcpy (name, "bob");
cout << "A CDog was made" << endl;
}
void CDog::growl( ) {
cout << “Grrrr" << endl;
}
41
Poodle: The evil subclass
• Since a poodle is a type of CDog, how can we
make class Poodle without re-writing a lot of
code?
• Does a poodle necessarily growl the same way
a CDog growls?
42
Class Poodle
(both header and cpp file)
#include "CDog.h“
class CPoodle:public CDog {
public:
CPoodle(int x);
};
Here’s where we inherit
from CDog
CPoodle::CPoodle(int x) : CDog (x){
cout << "A poodle was made" << endl;
}
43
What’s going on here?
Normal Constructor
Stuff
The super class’s constructor
is always called*; in this case,
we call the constructor which
takes an int.
CPoodle::CPoodle(int x) : CDog (x){
cout << "A poodle was made" << endl;
}
*Note: if you don’t explicitly call the super constructor, it looks for
a no-arguments constructor in the super class (which we don’t have)
44
What just happened?
• We created a poodle that has all the attributes and
all the methods that a CDog has
Problem:
CPoodle* myPoodle = new CPoodle (3);
myPoodle->growl ( ); // prints GRRRR
Poodles don’t go GRRRR, they “yip”
45
Overriding methods
• When you override a method, you give new
functionality to the class
• In this case, we need to override the growl method
for the poodle
• Simply redefine the method
46
A Better Poodle
(if there is such a thing)
#include "CDog.h"
class CPoodle:public CDog {
public:
CPoodle(int x);
void growl();
};
CPoodle::CPoodle(int x) : CDog (x){
cout << "A poodle was made" << endl;
}
void CPoodle::growl( ) {
cout << "Yip!" << endl;
}
Now when we tell the poodle to growl, it will print “Yip”
47
Access Keywords: public, private
(and protected)
• We can restrict access to attributes and
methods inside a class using public and
private
public – means “everyone can see it”
private – means “only that class can see it”
48
Bad Example
(won’t compile)
class X {
private:
int myInt;
// Constructor…
}
void main ( ) {
X* myX = new X ( );
myX->myInt = 42; // Not Allowed!
}
49
Working Example
class X {
public:
int myInt;
// Constructor…
}
void main ( ) {
X* myX = new X ( );
myX->myInt = 42; // Allowed!
}
50
Why private?
• Security: Keeps other classes from changing
attributes at random
• Design: forces other classes to use accessors
and modifiers to get to the information
• Encapsulation: the class is complete to itself
51
Memory Trace
Dog *d1, *d2;
d1 = new Dog (5, “bob”);
d2 = new Dog (5, “bob”);
d1 = d2;
null
52
Memory Trace
(declare the variables; they are dead)
Dog *d1, *d2;
d1 = new Dog (5, “bob”);
d2 = new Dog (5, “bob”);
d1 = d2;
null
d1
d2
53
Memory Trace
(bring d1 to life)
Dog *d1, *d2;
d1 = new Dog (5, “bob”);
d2 = new Dog (5, “bob”);
d1 = d2;
// Remember, new opens up
// space and calls the class
// constructor
null
d1
d2
54
Memory Trace
(bring d1 to life)
Dog *d1, *d2;
d1 = new Dog (5, “bob”);
d2 = new Dog (5, “bob”);
d1 = d2;
// Remember, new opens up
// space and calls the class
// constructor
null
d1
d2
55
Memory Trace
(bring d1 to life)
Dog *d1, *d2;
d1 = new Dog (5, “bob”);
d2 = new Dog (5, “bob”);
d1 = d2;
// Remember, new opens up
// space and calls the class
// constructor
null
d1
d2
rabid=false
weight=5
name=“bob”
56
Memory Trace
(bring d2 to life)
Dog *d1, *d2;
d1 = new Dog (5, “bob”);
d2 = new Dog (5, “bob”);
d1 = d2;
// Remember, new opens up
// space and calls the class
// constructor
null
d1
d2
rabid=false
weight=5
name=“bob”
57
Memory Trace
(bring d2 to life)
Dog *d1, *d2;
d1 = new Dog (5, “bob”);
d2 = new Dog (5, “bob”);
d1 = d2;
// Remember, new opens up
// space and calls the class
// constructor
null
d1
d2
rabid=false
rabid=false
weight=5
weight=5
name=“bob”
name=“bob”
58
Memory Trace
(comparison)
d1 and d2 do NOT occupy
the same space in memory,
so they are NOT ==
Example:
d1 == d2
evaluates to false
null
d1
d2
rabid=false
rabid=false
weight=5
weight=5
name=“bob”
name=“bob”
59
Memory Trace
(have d1 point to d2)
Dog *d1, *d2;
d1 = new Dog (5, “bob”);
d2 = new Dog (5, “bob”);
d1 = d2;
null
d1
d2
rabid=false
rabid=false
weight=5
weight=5
name=“bob”
name=“bob”
60
Memory Trace
(have j1 point to j2)
Dog *d1, *d2;
d1 = new Dog (5, “bob”);
d2 = new Dog (5, “bob”);
d1 = d2;
null
d1
d2
rabid=false
rabid=false
weight=5
weight=5
name=“bob”
name=“bob”
61
Memory Trace
(have j1 point to j2)
Now, d1 and d2 are ==
But no one is pointing to this
Because no one is pointing to
it, we can no longer reference
it. We call this piece of memory
garbage. We killed it!
null
d1
d2
rabid=false
rabid=false
weight=5
weight=5
name=“bob”
name=“bob”
62
Freeing up Memory
• Necessary to get rid of unused memory
• Rule: never set to null
• Use the delete ( ) operator
• Takes in a pointer to an object
• Usage (from previous example): delete (d1);
63
Summary of Inheritance
Benefits of inheritance
Allows for reuse of code
Good design
Use :<class name> to achieve this
Override methods in subclasses
== tests for same object in memory
64
C++ Classes
Object Oriented Programming
Object Oriented Programming
• Programmer thinks about and defines the attributes
and behavior of objects.
• Often the objects are modeled after real-world entities.
• Very different approach than function-based
programming (like C).
66
Reasons for OOP
Abstraction
Encapsulation
Information hiding
Inheritance
Polymorphism
Software Engineering Issues
67
Class: Object Types
• A C++ class is an object type.
• When you create the definition of a class you are
defining the attributes and behavior of a new type.
• Attributes are data members.
• Behavior is defined by methods.
68
Creating an object
• Defining a class does not result in creation of
an object.
• Declaring a variable of a class type creates an
object. You can have many variables of the
same type (class).
Instantiation
69
Information Hiding
• The interface to a class is the list of public data
members and methods.
• The interface defines the behavior of the class to the
outside world (to other classes and functions that
may access variables of your class type).
• The implementation of your class doesn't matter
outside the class – only the interface.
70
Information Hiding (cont.)
• You can change the implementation and nobody
cares! (as long as the interface is the same).
• You can use other peoples classes without fear!
• Wars will end, poverty and illness will be vanquished
from earth!
71
Inheritance
• It is possible to extend existing classes without seeing
them.
• Add whatever new behavior you want.
Example:
You have a class that represents a "student".
Create a new class that is a "good student".
Most of the behavior and attributes are the same,
but a few are different – specialized.
72
Polymorphism
• The ability of different objects to respond to the same
message in different ways.
Example:
Tell an int to print itself:
Now tell a double:
Now tell the Poly:
cout << i;
cout << x;
cout << poly;
73
Private vs. Public
• Public data members and methods can be
accessed outside the class directly.
• The public stuff is the interface.
• Private members and methods are for internal
use only.
• We will also see Protected.
74
Special Member Functions
Constructors: called when a new object is created
(instantiated).
can be many constructors, each can take different
arguments.
Destructor: called when an object is eliminated
only one, has no arguments.
75
Accessing Data Members
Data members are available within each method
(as if they were local variables).
Public data members can be accessed by other
functions using the member access operator "."
(just like struct).
76
Accessing class methods
Within other class methods, a method can be
called just like a function.
Outside the class, public methods can be called
only when referencing an object of the class.
77
What happens here?
class foo {
int i;
// # elements in the array
int a[10];// array 10 at most
// sum the elements
int sum(void) {
int i, x=0;
which i is
for (i=0;i<i;i++)
x+=a[i];
return(x);
}
...
it ?
78
Class Scope Operator ::
You can solve the previous problem using the "::"
operator classname::membername.
for (i=0;i<foo::i;i++)
x+=a[i];
79
Method names and ::
• Sometimes we put just a prototype for a member function
within the class definition.
• The actual definition of the method is outside the class.
• You have to use :: to do this.
80
Example
class foo {
...
int sum(void);
};
int foo::sum(void) {
int sum=0;
for (int i=0;i<foo::i;i++) {
sum += a[i];
}
return(sum);
}
81
Classes and Files
• The relationship between C++ class definitions and files
depends on the compiler.
• In general you can put class definitions anywhere! Visual
C++ wants one class per file.
• Most people do this:
class definition is in classname.h
any methods defined outside of the class definition
are in classname.cpp
82
static methods
• A static method is a class method that can be called
without having an object.
• Must use the :: operator to identify the method.
• Method can't access non-static data members! (they
don't exist unless we have an object).
83
Static Data Members
It is possible to have a single variable that is shared by all
instances of a class (all the objects).
declare the variable as static.
Data members that are static must be declared and initialize
outside of the class.
at global or file scope.
84
Static data member example
class foo {
private:
static int cnt;
public:
foo() {
foocount++;
cout << "there are now " << cnt
<< " foo objects << endl;
}
...
85
A Problem
• Class definitions usually in a ".h" file.
• Can be included by many other ".cpp" files, all part of the same
program.
• Can't declare and initialize a static data member in the ".h" file.
86
Solution
foo.h
class foo{
static int cnt;
foo.cpp
int foo::cnt=1;
…
};
f2.cpp
f1.cpp
#include "foo.h"
#include "foo.h"
...
...
int main() {
...
87
Operator Overloading
• We can define what some C++ operators mean
when applied to user defined objects.
• vector example (ivec.h) defines operators:
ostream <<
istream >>
+
[]
=
==
<
>
88
Operator Overloading Restrictions
You can't:
define a completely new operator
redefine the meaning of operators on built-in data types
(like int or double).
Change operator precedence or associatively.
89
Inheritance
• You can create a new class that inherits from an
existing class.
• You can add new members and methods.
• You can replace methods.
• The new class is a specialization of the existing class.
90
Terminology
• The existing class is called the base class.
• The new class is called the derived class.
• Objects of the derived class are also objects of
the base class.
91
Inheritance Example
• Base class is shape, represents the abstract
notion of a shape.
• Derived classes:
rectangle
circle
triangle.
• An object that is a circle is also a shape!
92
Protected Class members/methods
• We've already seen private and public.
• Protected means derived classes have access to
data members and methods, but otherwise the
members/methods are private.
93
Public/Private/Protected Inheritance
• Usually use public inheritance.
• Private and Protected inheritance change what
members/methods can be accessed outside of
the class.
94
Polymorphism
• You can treat derived class objects as objects
of the base class.
• The problem is that when doing this we don't
get access to the derived class methods!
95
Virtual Functions
• A virtual function is a method in a base class that
can be overridden by a derived class method.
• For example, we would like each object to "know"
which print() method to use.
• Declare the base class print method virtual, and
this happens!
96
The End
97