CPSC 427: Object-Oriented Programming
Michael J. Fischer
Functions and Methods
Call by value (recall)
Like C, C++ passes explicit parameters by value.
Call by pointer (recall)
Like C, pointer values (which I call reference values) are the things that can be stored in pointer variables.
Also like C, references values can be passed as arguments to functions having corresponding pointer parameters.
Call by reference
C++ has a new kind of parameter called a reference parameter.
I/O uses reference parameters
How should one choose the parameter type?
Parameters are used for two main purposes:
Sending data to a function: call by value For sending data to a function, call by value copies the data whereas call by pointer or reference copies only an address.
Sending data to a function: call by reference or pointer
Call by reference or pointer allows the caller’s data to be changed.
Use const to protect the caller’s data from inadvertane change.
Ex: int f( const int& x ) or int g( const int* xp ).
Prefer call by reference to call by pointer for input parameters.
Ex: f( 234 ) works but g( &234 ) does not.
Reason: 234 is not a variable and hence can not be the target of a pointer.
(The reason f( 234 ) does work is a bit subtle and will be explained later.)
Receiving data from a function
An output parameter is expected to be changed by the function.
Both call by reference and call by pointer work.
Call by reference is generally preferred since it avoids the need for the
caller to place an ampersand in front of the output variable.
Declaration: int f( int& x ) or int g( int* xp ).
Call: f( result ) or g( &result ).
The implicit argument
Every call to a class member function has an implicit argument, which is the object written before the dot in the function call.
this
The implicit argument is passed by pointer.
In the call ex.advance(3), the implicit argument is ex, and a pointer to ex is passed to advance().
The implicit argument can be referenced directly from within a member function using the keyword this.
Within the definition of advance(), count and this->count are synonymous.
Derivation
Class
relationships
Classes can relate to and collaborate with other classes in many
ways.
We first explore derivation, where one class modifies and extends another.
What is derivation?
One class can be derived from another.
Syntax:
A is the base class; B is the derived class.
B inherits the members from A.
Instances
A base class instance is contained in each derived class instance.
Similar to composition, except for inheritance.
Function members are also inherited.
Data and function members can be overridden in the derived
class.
Derivation is a powerful tool for allowing variations to a design.
Some uses of derivation
Derivation has several uses.
Example: Parallelogram
Example: Rectangle
Derived class Rectangle inherits area(), perimeter(), and print() functions from Parallelogram.
Example: Square
Derived class Square inherits the perimeter(), and print() methods from Parallelogram (via Rectangle).
It overrides the method area().
It adds the method inscribable() that determines whether this square can be inscribed inside of its argument square s.
Notes on Square
Features of Square.
Construction, Initialization, and Destruction
Structure of an object A simple object is like a struct in C.
It consists of a block of storage large enough to contain all of its data
members.
An object of a derived class contains an instance of the base class
followed by the data members of the derived class.
Example:
class B : A { …};
B bObj;
Then “inside” of bObj is an A-instance!
Example of object of a derived class
The declaration A aObj creates a variable of type A and storage size large enough to contain all of A’s data members (plus perhaps some padding).
aObj:
int x;
The declaration B bObj creates a variable of type B and storage size large enough to contain all of A’s data members plus all of B’s data members.
bObj:
int x; int y;
The inner box denotes an A-instance.
Referencing a composed object
Contrast the previous example to
class B { A aObj; …};
B bObj;
Here B composes A.
The embedded A object can be referenced using data member name aObj, e.g., bObj.aObj.
Referencing a base object
How do we reference the base object embedded in a derived class?
Example:
class A { public: int x; int y; …};
class B : A { int y; …};
B bObj;
Initializing an object
Whenever a class object is created, one of its constructors is called.
This applies not only to the “outer” object but also to all of its
embedded objects.
If not specified otherwise, the default constructor is called.
This is the one that takes no arguments.
If you do not define the default constructor, then the null constructor (which does nothing) is used.
Construction rules
The rule for constructing an object of a simple class is:
The rule for constructing an object of a derived class is:
Destruction rules
When an object is deleted, the destructors are called in the opposite
order.
The rule for an object of a derived class is:
Constructor ctors
Ctors (short for constructor/initializors) allow one to supply parameters
to implicitly-called constructors.
Example:
Initialization ctors
Ctors also can be used to initialze primitive (non-class) variables.
Example:
Multiple ctors are separated by commas.
Ctors present must be in the same order as the construction takes place – base class ctor first, then data member ctors in the same order as their declarations in the class.
Initialization not same as assignment
Previous example using ctors is not the same as writing
B( int n ) { y=n+1; x=n; };
Copy constructors
Move constructors
C++ 11 introduced a move constructor. Its purpose is to allow an object
to be safely moved from one variable to another while avoiding the
“double delete” problem.
We’ll return to this interesting topic later, after we’ve looked more closely at dynamic extensions.