CS 596 OODP
Classes: Constructors
[To Lecture Notes Index]
San Diego State University -- This page last updated Oct. 18, 1995

Contents of Classes: Constructors
Lecture
- Inline Function Members
- Classes and Files: Style Considerations
- Where Do I Put The Classes?
- Class inside of a Class
- Class inside of Function
- Initializing Class Data Members
- Conversion by Constructor
- Constructors and Destructors
- Stack with Constructors and Destructors
- Constants, Reference and Classes
- Constructors - initialization
- Static vs. Dynamic Constants
- Static Class Members
Method 1
class BankAccount
{
public:
setBalance(float amount) {balance = amount;} // inline
float getBalance() {return balance;} // inline
private:
float balance;
};
#include <iostream.h>
main()
{
BankAccount me;
me.setBalance(2.0); // me.balance = 2.0
cout << me.getBalance() << "\n";
}
Inline Function Members
Method 2
#include <iostream.h>
class BankAccount
{
public:
void setBalance(float amount); // OK without inline
inline float getBalance();
private:
float balance;
};
inline void BankAccount::setBalance(float amount)
{
balance = amount;
}
inline float BankAccount::getBalance()
{
return balance;
}
main()
{
BankAccount me;
me.setBalance(2.0);
cout << me.getBalance() << "\n";
}
Each class requires at least two files:
- file for class definition
-
- file(s) for implementation of class function members
Header file for class definition
- // File:
- bankAccount.hh
- // Created:
- Sunday, Nov. 1, 1992, 3:05 PM
- // Author:
- Roger Whitney
-
- // Copyright (c)
- 1992 by SDSU
-
- #ifndef
- _bankAccount_HH
- #define
- _bankAccount_HH
-
- #ident
- "This line is used by SCCS for version control"
-
- // Defines the interface to the BankAccount class
- class BankAccount
- {
-
- public:
-
- void setBalance(float amount);
-
- float getBalance();
-
-
-
- private:
-
- float balance;
- };
-
- #endif
- // _bankAccount_HH
Classes and Files: Style Considerations
Continued
File for class Implementation
- // File:
- bankAccount.cc
- // Created:
- Sunday, Nov. 1, 1992, 3:11 PM
- // Author:
- Roger Whitney
-
- // Copyright (c)
- 1992 by SDSU
-
- #ident
- "This line is used by SCCS for version control"
-
- #include
- "backAccount.hh"
-
-
- // Implementation of BankAccount
- void BankAccount::setBalance(float amount)
- {
-
- balance = amount;
- }
-
- float BankAccount::getBalance()
- {
-
- return balance;
- }
Classes and Files: Style Considerations
Continued
File for main program
- // Standard Comment line deleted to save space
-
- #include
- "bankAccount.hh"
- #include
- <iostream.h>
-
- // Sample program using bankAccount class
- main()
- {
- BankAccount me;
-
- me.setBalance(2.0);
- cout << me.getBalance() << endl;
-
- }
Sample makefile
- test: bankAccount.o main.c
- CC bankAccount.o main.cc -o test
-
- bankAccount.o: bankAccount.hh bankAccount.cc
- CC bankAccount.cc -c
-
- clean:
-
- rm *.o
Inline Functions and Files: Style Consideration
Do not use #define to obtain more efficient code, use inline functions
Access functions can be made inline
Use separate file to define inline functions
BankAccount.hh
class BankAccount
{
public:
void setBalance(float amount);
float getBalance();
private:
float balance;
};
BankAccount.cc //Inline version
inline void BankAccount::setBalance(float amount)
{ balance = amount; }
inline float BankAccount::getBalance()
{ return balance; }
BankAccount.cc // Normal Version
void BankAccount::setBalance(float amount)
{ balance = amount; }
float BankAccount::getBalance()
{ return balance; }
* Global
As we have seen classes can be listed at the global level
Most common
* Class
A class can be nested inside another class
Useful
* Local
A class can be nested inside a function
Rare
#include <iostream.h>
class Outside
{
public:
class Inside
{
public:
int chocolate;
void taste(int it) {chocolate = it;}
};
int hard;
void melt(int slow) {
GoodStuff.taste(slow);
hard = slow;}
private:
Inside GoodStuff;
}
main()
{
Outside coating;
Inside try; // Legal - version 2, illegal - version 3
Outside::Inside me; // Legal - version 3, illegal - version 2
coating.melt(5);
cout << coating.hard << "\n";
}
myFunction(int size)
{
class WhyInHere
{
public:
int noIdea;
};
WhyInHere beatsMe;
beatsMe.noIdea = size; // Does not do much, does it?
}
main()
{
myFunction(5);
}
#include <iostream.h>
class BankAccount
{
public :
float balance;
BankAccount(float amount = 0.0);
};
BankAccount::BankAccount(float amount)
{
cout << "Constuctor: " << amount << endl;
balance = amount;
}
main()
{
BankAccount A;
BankAccount B(1.0);
BankAccount C = 2.0;
BankAccount D = BankAccount(3.0);
BankAccount* E = new BankAccount(4.0);
A = 5.0;
B = BankAccount(6.0);
}
Output
Constuctor: 0
Constuctor: 1
Constuctor: 2
Constuctor: 3
Constuctor: 4
Constuctor: 5
Constuctor: 6
Multiple Parameters
#include <iostream.h>
class BankAccount
{
public :
float balance;
BankAccount(float amount, int NotUsed);
};
BankAccount::BankAccount(float amount, int NotUsed)
{
cout << "Constuctor: " << amount << endl;
balance = amount;
}
void main()
{
BankAccount A(1.0, 1);
BankAccount B = BankAccount(2.0, 2);
BankAccount C = (3.0, 3); // Compile Error
A = BankAccount(4.0, 4);
B = (4.0, 4); // Compile Error
}
#include <iostream.h>
class BankAccount
{
public :
float balance;
BankAccount(float amount, int NotUsed = 0);
};
BankAccount::BankAccount(float amount, int NotUsed)
{
cout << "Constuctor: " << amount << endl;
balance = amount;
}
main()
{
BankAccount A(1.0, 2);
A = 5.0; // Conversion
}
Output
Constuctor: 1
Constuctor: 5
Problem
#include <iostream.h>
class BankAccount {
public :
float balance;
BankAccount(float amount );
};
BankAccount::BankAccount(float amount){
balance = amount;
}
class ThisWorksAccount {
public :
float balance;
};
main()
{
BankAccount A; // Compile error
ThisWorksAccount A;
}
Output
Error: cannot find constructor for class matching BankAccount::BankAccount()
Default Constructor
The compiler generates default constructor with no arguements if there is no
other constructor in the class
#include <iostream.h>
class BankAccount
{
public :
float balance;
BankAccount(float amount = 0.0);
~BankAccount();
};
BankAccount::BankAccount(float amount){
cout << "Constuctor: " << amount << endl;
balance = amount;
}
BankAccount::~BankAccount()
{ cout << "Close out an account: "<< balance << endl;}
void main()
{
BankAccount A;
BankAccount B(1.0);
BankAccount C = 2.0;
BankAccount D = BankAccount(3.0);
BankAccount* E = new BankAccount(4.0);
A = 5.0;
}
Output
Constuctor: 0 Close out an account: 3
Constuctor: 1 Close out an account: 2
Constuctor: 2 Close out an account: 1
Constuctor: 3 Close out an account: 5
Constuctor: 4
Constuctor: 5
Close out an account: 5
Constructors and Destructors
#include <iostream.h>
class BankAccount
{ public :
float balance;
BankAccount(float amount = 0.0);
~BankAccount();};
BankAccount::BankAccount(float amount)
{ balance = amount;
cout << "Start up an account: " << balance << endl;}
BankAccount::~BankAccount()
{ cout << "Close out an account: "<< balance << endl;}
void functionCallWithLocalAccount()
{ BankAccount you(10);
cout << "Inside Function Call\n";}
void main()
{ BankAccount me(5);
cout << "Before function call\n";
functionCallWithLocalAccount();
cout << "After function call\n";}
Output
Start up an account: 5
Before function call
Start up an account: 10
Inside Function Call
Close out an account: 10
After function call
Close out an account: 5
Example Two
#include <iostream.h>
class BankAccount
{ public :
float balance;
BankAccount(float amount = 0.0);
~BankAccount();
};
BankAccount::BankAccount(float amount)
{ balance = amount;
cout << "Start up an account: " << balance << endl;
}
BankAccount::~BankAccount()
{ cout << "Close out an account: "<< balance << endl;
}
void main()
{
BankAccount me[5];
}
Output
Start up an account: 0
Start up an account: 0
Start up an account: 0
Start up an account: 0
Start up an account: 0
Close out an account: 0
Close out an account: 0
Close out an account: 0
Close out an account: 0
Close out an account: 0
Explain This?
#include <iostream.h>
class BankAccount
{ public :
float balance;
BankAccount(float amount = 0.0);
~BankAccount();};
BankAccount::BankAccount(float amount)
{ balance = amount;
cout << "Start up an account" << balance << endl;}
BankAccount::~BankAccount()
{ cout << "Close out an account"<< balance << endl;}
BankAccount nestedFunction()
{ BankAccount you(10);
cout << "Inside nested Function\n";
return you;}
void main()
{ BankAccount me(5);
cout << "Before function call\n";
me = nestedFunction();
cout << "After function call\n";}
Output
Start up an account5
Before function call
Start up an account10
Inside nested Function
After function call
Close out an account10
Close out an account10
#include <iostream.h>
#include <assert.h>
class Stack
{
friend ostream& operator<<(ostream& , Stack&);
public:
Stack(int StartSize = 10);
~Stack();
int isEmpty() const;
int isFull() const;
void push(int item);
float pop();
private:
float* stack;
int nextFreeLocation;
int size;
void grow();
};
Stack::Stack(int StartSize)
{
size = StartSize;
stack = new float[StartSize];
nextFreeLocation = 0;
}
Stack::~Stack()
{
delete stack;
}
Stack with Constructors and Destructors
void Stack::grow()
{
float* oldStack = stack;
int oldSize = size;
size += size/2 + 1;
stack = new float[ size ];
assert(stack != 0 ); // Why not set_new_handler?
// copy elements of old array into new
for ( int ix = 0; ix < oldSize; ++ix )
stack[ ix ] = oldStack[ ix ];
delete oldStack;
}
int Stack::isEmpty() const
{
if (nextFreeLocation == 0) return 1;
else return 0;
}
int Stack::isFull() const
{
return 0;
}
void Stack::push(int item)
{
if (nextFreeLocation == size) grow();
stack[nextFreeLocation++] = item;
}
Stack with Constructors and Destructors
float Stack::pop()
{
return stack[--nextFreeLocation];
}
ostream& operator<<(ostream& output, Stack& aStack) {
output << "Stack(" ;
output << aStack.stack[aStack.nextFreeLocation - 1];
for (int K = aStack.nextFreeLocation - 2; K>= 0; K--)
output << "," << aStack.stack[K];
output << ")";
return output;
}
void main()
{
Stack books(11);
for (int k = 0; k < 200; k++)
books.push(k);
cout << books << endl;
};
Modular Design Rules
Don't let a few objects run the entire show
Give each object some intelligence
Supports:
- Decomposability
- Composability
- Continuity
- Understandability
class BadNews
{
public:
int Sam = 5;
int& AReference = Sam; // Compile Error
const int AConstant = 10; // Compile Error
int x;
};
#include <iostream.h>
class ConstDataMember {
public:
int& AReference;
const int AConstant;
int x;
ConstDataMember(int why, int not = 13);
friend ostream& operator<<(ostream&,
const ConstDataMember &it);
};
ConstDataMember::ConstDataMember(int why, int not) :
AConstant(why) , AReference(not) // initialization phase
{x = why + not;}; // assignment phase
ostream& operator<<(ostream& output,
const ConstDataMember &it) {
output << it.AReference << '\t'
<< it.AConstant << '\t'
<< it.x << '\t';
return output;
};
void main() {
ConstDataMember Fine(7, 11);
ConstDataMember Well(10);
cout << Fine << Well;
};
Constructor - Destructor Order
#include <iostream.h>
class BankAccount {
public :
float balance;
BankAccount(float amount = 0.0);
~BankAccount();
};
BankAccount::BankAccount(float amount){
cout << "Constuctor: " << amount << endl;
balance = amount;
};
BankAccount :: ~BankAccount()
{ cout << "Close out an account: "<< balance << endl; }
class Bank {
public:
BankAccount A;
BankAccount B;
BankAccount C;
Bank();
~Bank() { cout << "End Bank" << endl;};
};
Bank :: Bank() : B(5) { cout << "Start Bank" << endl; C = 10;};
void main() {
Bank X;
};
Output
Constuctor: 0 Close out an account: 10
Constuctor: 5 End Bank
Constuctor: 0 Close out an account: 10
Start Bank Close out an account: 5
Constuctor: 10 Close out an account: 0
main()
{
const int Size = 100; // Static Constant
int OK[Size]; // Compiles fine
}
class NoGo
{
public:
const int ASize; // Dynamic Constant
int NoWay[Size]; // Compile Error
NoGo (int whyNot = 100);
};
NoGo ::NoGo (int whyNot ) :
ASize(why) // initialization phase
{};
One Copy per Class
class StudentRecord
{
public :
char *firstName;
static char university[10];
static char* getUniversity();
};
char* StudentRecord::getUniversity() {
return university;
}
char StudentRecord::university[10] = "SDSU";
#include <iostream.h>
void main()
{
StudentRecord me;
StudentRecord you;
me.firstName = "Roger";
you.firstName = "Pete";
cout << me.firstName << "\n" // Prints Roger
<< me.university << "\n" // Prints SDSU
<< StudentRecord::university << "\n" // Prints SDSU
<< me.getUniversity() << "\n" // Prints SDSU
<< StudentRecord::getUniversity(); // Prints SDSU
}
Static Class MembersThey can change value
#include <iostream.h>
class ChangeStaticMember {
public:
int getStatic() { return StaticNotConst; }
void setStatic(int x) { StaticNotConst = x; }
private:
static int StaticNotConst;
};
int ChangeStaticMember :: StaticNotConst = 5;
void main()
{
ChangeStaticMember me;
ChangeStaticMember you;
me.setStatic(10);
cout << me.getStatic() << endl; // prints 10
me.setStatic(20);
cout << you.getStatic() << endl; // prints 20
}
Static Members can't Access Nonstatic
class StudentRecord
{
public :
char *firstName;
static char university[10];
static char* getName();
};
char* StudentRecord::getName() {
return firstName; // Compile Error
}
char StudentRecord::university[10] = "SDSU";
#include <iostream.h>
void main()
{
StudentRecord me;
}