Title: C for Java Programmers
1C for Java Programmers
2Last Week I covered
- Can you even remember last week?
- Things arising from the test
- C Class Structure
- Constructors
- Member Functions
- Default Arguments
- Inline Functions
- DMA in Classes
- Passing Objects to and from Functions
3Today were going to consider
- Todays agenda covers
- 2) Clarify some Confusion
- 3) Shallow and Deep Copy
- 4) Copy Constructors
- 5) Function Overloading
- 6) Constructor Overloading
- 7) the This pointer
- 8) Operator Overloading
41) The real danger of CS
Some complaints about the amount of
coursework. If you are going to blame anyone
5Larry Wall guy who wrote Perl
6Conclusive Proof
Glasses
72. Pointers as class variables
- Everything we that have used pointers for up to
now, we can use in a class also. - So the variables in your class can be dynamic
too. - This means that we need to setup the memory for
these dynamic variables in the constructor -
using the new statement. - Therefore each object will have its own bit of
the heap, where its dynamic variables are being
stored.
8Constructor Example
- class Deck
- public
- vector(int s)
- private
- Card cardArrayPtr
- int size
-
- DeckDeck(int s 1)
- size s
- cardArrayPtr new Cards
Define a pointer to the cards that will make up
out deck.
Setup the memory for our dynamic array of cards.
9Free that memory
- But all this memory weve set up needs to be
freed. - This does not happen automatically you have to
do it. - Golden Rule If you setup memory in a
constructor, Delete it in the destructor. - That way, when an object dies, it tidies up all
of its loose ends by itself.
10Destructor Example
- DeckDeck(int s 1)
- size s
- cardArrayPtr new Cards
-
- DeckDeck()
- delete cardArrayPtr
- cardArrayPtr NULL
-
Because it was a dynamic array we can free the
memory for it in one line
Good habit stop that pointer from dangling
113. Copies are created Everywhere
- Last week we learnt that when you pass anything
to or from a function by value a copy of it is
made. - Unless we tell C otherwise, this copy will be a
bit-wise copy. - Normally this isnt a problem and we dont even
know a copy has been made it is deleted almost
straight away. - But if we copy a class that contains pointers as
variables it CAN be a problem.
12Graphically Deck Example
- class Deck
- public
- vector(int s)
- Card cardArrayPtr
- int size
-
- DeckDeck(int s)
- size 52
- cardArrayPtr new Cards
-
- DeckDeck()
- delete cardArrayPtr
- cardArrayPtr NULL
52
stack
heap
13Graphically Deck Example
myDeck
52
size
cardArrayPtr
stack
- DeckDeck()
- delete cardArrayPtr
- cardArrayPtr NULL
heap
14Shallow Copy
- The above example was an illustration of a
shallow copy. - Shallow Copies are dangerous, because when they
are deleted we can lose valuable parts of the
original. - This is the default behaviour - just like the
default behavour of the Java .clone() method. - But when we have pointers and DMA being performed
in our class, we need a Deep Copy.
15Deep Copy
- Deep copying recursively copies any object that
is pointed at by the copied object. - A check is performed to see what pointers exist
in our object to be copied. - If one is found it is followed and another check
is performed. - This carries on until no pointers are found.
- Everything looked at in the above algorithm is
copied. - This means now all of our original data is safe.
16Deep Copying that deck
myDeck
52
size
cardArrayPtr
stack
heap
17Its Recursive.
Shoe
Copy
6
decks
deckArrayPtr
stack
52
size
cardArrayPtr
heap
18So how do I do a deep copy?
- Java can override shallow copy behaviour
automatically - In fact its .clone() method will do a deep copy
where it thinks its appropriate. - Old languages like Smalltalk-80, by contrast
provide separate shallowCopy and deepCopy member
functions - C uses a Copy Constructor. You write the deep
copy.
194. Copy Constructor
- Constructors usually build objects from nothing.
A copy constructor for a class can be called to
copy an existing object. - For example both of the following statements call
the copy constructor - Deck d2 new Deck(d1)
- Deck d2 d1
-
- If the programmer does not define a copy
constructor for a class, C generates a basic
member-by-member (shallow) one
20Copy Constructor Syntax
- When we include the following syntax the bitwise
copy is bypassed - classname (const classname o)
- //body of the constructor
-
- In our code we would have something like
- DeckDeck (const Deck d)
21Only used for Initialising
- Copy Constructors are now used for assigning
- Explicitly they are only apply to
initialisations - When an object initialises another in a
declaration - When a copy is made as an ojects is passed to a
function. - When a temporary object is generated as a return
value - Deck x y //y explicitly initialising x
- someFunction(x) //x passed as a parameter
- someFunction(aFunctionReturningADeck(y))
- //receiving a temporary return object
22Example
- DeckDeck(int s)
- size s
- cardArray new Cards
-
- DeckDeck(const Deck d)
- size d.size
- cardArray new Cardsize
- for(int i1 iltsize i)
- cardArrayi d.cardArrayi
-
-
Constructor
Copy Constructor
copy across those cards
236. Overloading in Classes
- What we have been doing here is overloading.
- In some languages, such as Delphi, you have to
indicate an overloaded function using the
overload keyword. - This used to be the case when C was created-
now it is obsolete. - This makes sense because it should be obvious to
the compiler when we are overloading a function.
24Member Function Overloading
- Powerful Tool
- Used in almost every program youll write
- Same Function names different parameters.
- For example a cube function
-
- int numbercube (int n) return nnn
- double numbercube (double n) return nnn
25Whats Allowed?
- Functions with the same name but
- different parameter types
- different numbers of parameters
- What is not allowed
- just a different return type
- same parameters with a different syntax
- int numbercube(int p)
- double numbercube(int p)
- int numbercube(int p)
- int numbercube(int p)
parameters identical
parameters identical too
26Overloading Constructors
- Constructors are just functions so they can be
overloaded. - A copy constructor is itself just an overloaded
version of the actual constructor - 3 reasons for overloading functions
- to gain flexibility
- to allow both initialised and uninitialised
objects - to define copy constructors
27Allow different info to be initialised
- Have as many constructors as you feel like you
need to make your coding easy - class Team
-
- Team()
- Team(char c)
- Team(char c, int gamesPlayed)
- Team(char c, int w, int l, int d)
- Team(const Team t)
- ...
-
28Or same info in different formats
- class Date
-
- int d, m, y
- public
- Date(int _m, int _d, int _y)
- Date(char _s)
- show() cout ltlt d ltlt - ltlt m ltlt - ltlt y ltlt
endl -
- Date(int _m, int _d, int _y)
- d _d m_m y_y
-
- DateDate(char _s)
- sscanf(_s, dcdcd, d, m, y )
Inline Function
Unformats the text, so we can initialise the
object in the format dd/mm/yyyy
29Uninitialised Initialised Objects
- Overloaded Constructors allow you to set up both
Initialised and Uninitialised Objects - This is vital in setting up dynamic arrays (as
you might have done in the coursework). - This is because
30Defaults vs Overloading
- You can use default arguments or overloaded
functions - to do the same job. For Example
-
- void getLine(char from, char to)
- void getLine(char from, char to, char d)
- void getLine(char from, char to, char
d\n) - getLine(input, output)
- getLine(input, output, )
- General Rule Dont use overloaded functions when
defaults will do the job.
Overloaded
Default Arguments
Both prototypes will process these commands
317. The This pointer
- What if we want to pass the class we are in to a
function as a parameter? - Furthermore we know if an object is sent to a
function a copy is made which is then deleted -
what happens then!? - All classes automatically have a pointer called
this which solves these problems.
328. Operator Overloading
- In C you can also overload operators - , -, ,
- You can make almost any operators act any way you
want with your classes by overloading them. - They mean that it C you really can use classes
as easily as you would fundamental types. - Although its called overloading it really is more
like creating an operator from scratch.
33The Syntax
- Member operator functions look different to
non-member operator functions. - The syntax for setting up operators inside your
classes is as follows - return-type classNameoperator(argList)
placeholder for the operator itself
Those again
often the same type as the class
operator keyword
A list of parameters that the operator can accept
34Why do we need to?
- Imagine we had a coordinates class
- class coordinates
- int x,y
- public
- coordinates(int _x, int _y) x_x y_y
- display() cout ltlt ( ltlt x ltlt , ltlt y ltlt
)\n - coordinates operator(coordinates c)
-
- And in our main program we try
- int main()
- coordinates pointA(2,3)
- coordinates pointB(-1,-1)
- coordinates pointC pointA pointB
-
-
-
ERROR!
35Overloading Simple Operators
- We overload all the simple mathematical operators
in much the same way. For example - class coordinates
- int x,y
- public
- coordinates()
- display() cout ltlt ( ltlt x ltlt , ltlt y ltlt
)\n - coordinates operator(coordinates c)
-
-
- coordinates coordinatesoperator(coordinates
c) - coordinates temp
- temp.x (this).x c.x
- temp.y (this).y c.y
- return temp
-
-
Now our main program would work
36Overloading Simple Operators
- In this case the parameter only takes one
operator - You might expect two, but we only need one
because it is acting within the first object
already. - Most often the return type is another object of
the class. This allows to have statements like - pointA pointB pointC
- (pointA pointB).display()
37Same setup for other operators
- coordinates coordinatesoperator-(coordinates c)
- coordinates temp
- temp.x x - c.x
- temp.y y - c.y
- return temp
-
- coordinates coordinatesoperator()
- coordinates temp
- temp.x x 1
- temp.y y 1
- return temp
-
Creating a minus operator is almost identical
We can even overload to just add one to our
coordinates
38You can have several versions
- coordinates coordinatesoperator(int i)
- coordinates temp
- temp.x x i
- temp.y y - i
- return temp
-
- coordinates coordinatesoperator(double d)
- coordinates temp
- temp.x int(x d)
- temp.y int(y d)
- return temp
-
Here we have one version that takes in an int as
a parameter
And another overloaded version that uses doubles
39Restrictions
- You can overload almost any operator so it works
with your classes. - What cant you do?
- alter the precedence of an operator
- change the number of operands
- cant have default arguments
- Cant overload . . ?
- Try and make your overloading make sense.
- Operators are inherited by any derived class.
40Now were cooking
- So far so good. Now we can use operators with
our classes - pointA pointB
- pointA
- pointA - 4
- What would happen compile the statement
- 10 pointA
ERROR!
The integer is a built in type and so no
operation between an integer and a
coordinates object exists. Doh.
41How do we fix this problem?
- Remember friends functions from last lecture?
- No well this is what they are used for.
- We set up a normal function that takes in TWO
parameters - coordinates operator(coordinates c, int a)
- coordinates temp
- temp.x c.x a
- temp.y c.y a
- return temp
-
No operator because this ISNT a member
function
42Were using Non-Member functions
- And now we need a function for the opposite
order - coordinates operator(int a, coordinates c)
- coordinates temp
- temp.x a c.x
- temp.y a c.y
- return temp
-
- As it stands this would still not work, because x
and y are private variables of the coordinates
class. - This is why we need to declare this function as a
friend within the coordinates class.
Almost identical except the parameters types have
been switched round.
43Friend Overloading
- So all we need is to put the following lines in
our coordinates class -
- friend coordinates operator(int a, coordinates
c) - friend coordinates operator(coordinates c, int
a) - And now both the following expressions will work
- 100 pointB
- pointA 100
44Overloading Special Operators
- We can even set up special operators to work with
our classes, such as ( ) -gt and , - For example if we overload we might have
-
- int coordinatesoperator(int i)
- return (i0) ? x y
-
- Now the expression pointA1
- Translates to the call pointA.operator (1)
- And would now return the x-value of our
coordinate.
45Exercise of the day (1)
- What is the output of the following program
include ltiostream.hgt class do_it public
do_it() do_it(const do_it d) cout ltlt "I
" do_it() cout ltlt "will not\n" void
do_something(do_it d) cout ltlt "I ... " do_it
operator(do_it d) cout ltlt "certainly "
return d main() do_it d
do_something(d)
46Exercise of the day (2)
- Write a class sizedArray with a constructor and
an overloaded index operator () such that it
can be used in the following piece of code
int main() sizedArray a(10) for (int
I0Ilt10I) aI I7 sizedArray
b(1000) for (int I0Iltb.size()I) bI
I
47Important - Trouble comes in 3s
- A class typically needs to define explicitly
- a copy constructor
- an assignment operator
- a destructor
- only if it makes use of Dynamic Memory
Allocation. - Otherwise the automatic generations are fine.
- However if you need to define one of these, you
probably need to define them all.