C++ Features
Constant Arguments
The keyword const is added to the beginning of an argument declaration to prevent the
argument from being modified within the called function.
• This will also prevent temporary modification of the argument.
General guidelines as to when to use constant arguments:
• When the argument is used in an output statement only.
• When the argument is used on the right side of the assignment operator only.
void printValue( const int value ) { int updateValue( const int oldValue ) {
cout << value << endl; int value;
return; value = oldValue * 3;
} return value
// lower camel case naming }
In general an argument that uses Pass-by-Value should be constant.
• There are also times when an argument that uses Pass-by-Reference should be
constant.
An array is a perfect example.
int calculateSum( const int intArray[], const int size ) // Definition header
intArray is using Pass-by-Reference which means that it can be permanently modified
within calculateSum.
• Prevent this by passing intArray as a constant reference.
The copy constructor is another perfect example.
Stack::Stack( const Stack & oldStack ) // Definition header – .cpp file
oldStack is being copied to create a new Stack class instance.
• It is important that the state of oldStack is unchanged by the copy operation.
oldStack uses Pass-by-Reference so that the copy constructor is not called twice.
• Otherwise, the copy constructor is called once to create a temporary copy of oldStack
that is placed on the runtime stack and once to create the new Stack class instance.
Including Modules/Libraries in C++
Modules/libraries are used in C++ to declare and define Abstract Data Types. A module
in C++ consists of:
• a header file (.h)
• a implementation file (.cpp)
When adding a module to an application only include the header file and never include
the implementation file.
A simple application with one user-defined module will consist of:
• a driver/main file (.cpp)
• a module header file (.h)
• a module implementation file (.cpp).
Both the driver/main file and the implementation file will include the header file only.
• This will provide them both with the required declarations and definitions.
// standard module/library includes
#include <iostream>
// user-defined module/library includes
#include “gamradtkX.h” // [Link] & [Link]
using namespace std;
// rest of the driver/main file or the implementation file
Classification of Class Functions
Each class function can be classified in one of three categories:
1. Manager
a. Responsible for the creation and destruction of a class instance.
b. Examples: constructors and destructors
2. Accessor
a. Responsible for retrieving the state information of a class instance without
modifying its state.
b. These functions are commonly referred to as “getter” functions.
c. Examples: getValue, empty, full, print, peek
d. These function are generally constant functions
3. Mutator or Modifier
a. Responsible for altering the state information of a class instance.
b. These functions are commonly referred to as “setter” functions
c. Examples: setValue, push, pop
class Class1 { // header file
public:
Class1( ); // Manager
~Class1( ); // Manager
int getValue( ) const; // Accessor – returns values
void setValue( const int ); // Mutator – assigns values
private:
int value;
};
// implementation file
Class1::Class1( ) { Class1::~Class1( ) {
} }
int Class1::getValue( ) const { void Class1::setValue( const int oldValue ) {
return value; value = oldValue;
} return;
// upper camel case naming – MyClass }
Class Instantiation in C++
When a new class instance is created or a new class object is instantiated there are three
things that will automatically occur:
1. Storage allocation
2. Initialization using Base/Member initialization list
3. Assignment using the body of the constructor
The enforcement of constant members occurs between actions 2 and 3.
class Class2 { // header file
public:
Class2( ); // default constructor
~Class2( ); // destructor
private:
const int FIVE = 5; // ERROR
// Assignment must be performed in the body of the constructor
// Replace with: const int FIVE;
const int ZERO; // ERROR
// All constants must be initialized
};
Initialization is done using the Base/Member initialization list:
Class2::Class2( ) : FIVE( 5 ), ZERO( ) // Definition header – .cpp file
Class2::Class2( ) : FIVE( 5 ), ZERO( 0 ) // FIVE = 5 and ZERO = 0
// Also works with variables
class Class3 { // header file
public:
Class3( ); // default constructor
Class3( const Class3 & ); // copy constructor
~Class3( ); // destructor
private:
const int MAX_SIZE = 10; // ERROR
// Storage allocation is handled before constants are enforced
enum Limit { MAX_SIZE = 10 }; // OK
enum { MAX_SIZE = 10 }; // OK – doesn’t have to be named
int intArray[ MAX_SIZE ];
};
Referencing Multiple Class Instances
int main( ) { // driver/main file
// instance1 is calling/invoking the default constructor
Class3 instance1;
// instance2 is calling/invoking the overloaded/parameterized/
// copy constructor
Class3 instance2( instance1 );
return 0;
}
Class3::Class3( const Class3 & oldInstance ) { // implementation file
for ( int position = 0; position < MAX_SIZE; ++position )
intArray[ position ] = [Link][ position ];
}
intArray[ position ] // calling instance – instance2
// implicit reference to the instance being instantiated
[Link][ position ] // copied instance – instance1
// explicit reference to the existing instance
The “this” pointer is an explicit reference to the class instance that called the active class
function.
intArray[ position ] // calling instance – instance2
this->intArray[ position ] // alternative form using the “this” pointer
(*this).intArray[ position ] // alternative form using the “this” pointer