Computer Methods Lecture 2
Computer Methods Lecture 2
ENEL3CCH1
Week Three
Extending the sample application
A deeper look at functions
Message.h Message.cpp
Class header file #include “Message.h”
#pragma once
#include <iostream> Declares the class
#include <string> void Message::setMsg(std::string Msg1) { this->Msg = Msg1; }
interface… everything
the caller needs to
class Message { std::string Message::getMsg() { return Msg; }
know about the class
private:
std::string Msg; void Message::display() {
std::cout << Msg;
public: }
void setMsg(std::string Msg1);
std::string getMsg(); Message::Message() { //define default constructor
void display(); this->Msg = "Empty string!!!";
Message(); //default constructor }
Message(std::string); //construct overload Class implementation file
}; Message::Message(std::string Msg) {
this->Msg = Msg; Contains method
} implementations for the class
Let us extend the OOP demo
• Add static member vars
These are common to all instances of the class; so if one object modifies a static var, all other instances of that
class will see the change. It is a shared resource.
For example:
Use this to count the total number of messages sent by all instances of the class (do this as an execrcise)
Or use this to count the number of class instances currently in existence
For example:
Use this to print the total number of messages sent by all instances of the class (do this as an exercise)
Or to print the total number of class instances in existence
• Add a destructor
that indicates the destruction of an object and the number of class instances
still left.
Static var initialisation…
• Not optional!
Create and use a static member variable • Not inside any function
Message.cpp
#include “Message.h”
Message.h int Message::NumOfMessageObjects = 0;
Static is a storage class…
#pragma once • Only inserted into the declaration
#include <iostream> • Not inserted into the definition void Message::setMsg(std::string Msg1) { this->Msg = Msg1; }
#include <string>
std::string Message::getMsg() { return Msg; }
class Message {
private: void Message::display() {
std::string Msg; std::cout << Msg;
static int NumOfMessageObjects; }
…with
public: class
void setMsg(std::string Msg1); scope Message::Message() { //define default constructor
std::string getMsg(); Msg = "Empty string!!!“;
NumOfMessageObjects++;
void display(); }
Declare Use
Message.cpp
Add a static member function…
#include “Message.h”
int Message::NumOfMessageObjects = 0;
Message.h
void Message::setMsg(std::string Msg) { this->Msg = Msg; }
#pragma once
#include <iostream> std::string Message::getMsg() { return Msg; }
#include <string>
void Message::display() { Static method…
class Message { std::cout << Msg; • Can only use static vars
private: } • cannot use this->
std::string Msg;
static int NumOfMessageObjects; int Message::ObjectCount() {
return NumOfMessageObjects;
public: }
void setMsg(std::string Msg1);
std::string getMsg(); Message::Message() { //define default constructor
Msg = "Empty string!!! ";
void display(); NumOfMessageObjects++;
static int ObjectCount(); }
class
class Message
Message {{ int Message::ObjectCount() {
private:
private: return NumOfMessageObjects;
std::string
std::string Msg;
Msg; }
static
static int
int NumOfMessageObjects;
NumOfMessageObjects;
Message::Message() { //define default constructor
public:
public: Msg = "Empty string!!! ";
void
void setMsg(std::string
setMsg(std::string Msg1);
Msg1); NumOfMessageObjects++;
std::string
std::string getMsg();
getMsg(); }
void
void display();
display(); Message::Message(std::string Msg) {
static
static int
int ObjectCount();
ObjectCount(); this->Msg = Msg;
NumOfMessageObjects++;
Message();
Message(); //default
//default constructor
constructor }
Message(std::string);
Message(std::string); //construct
//construct overload
overload
~Message();
~Message(); //destructor
//destructor Message::~Message() {
};
}; std::cout << --NumOfMessageObjects << " remaining objects/n";
}
MyProg.cpp
#include <iostream> Remember the lecture 2 exercise…
#include <string>
#include "Message.h" Use static vars and methods to count
int main() {
and display the total number of
Message MsgObj1("Howzit! \n"); messages send by all instances of the
std::cout << "Object " << MsgObj1.ObjectCount() << ": "; Message class.
MsgObj1.display();
• If any instance of the class modifies the static var, all other
instances of the class will see the modification…
Static member variables…
• Static members vars are initialised BEFORE any object is created
A
OOP is not a language methodology
OBJECTs
are central to OOP
What is OOP?
One must understand the philosophical basis of OOP before the
its syntactical expression in C++.
Philosophical
Abstraction concepts Inheritance
Polymorphism
Encapsulation Object
Class
Common issues noted in class and labs
For example: I created the Message class and used it in the Howzit
example. I made the class generic and reusable. It can deliver any
message. It is not a Howzit class! It is more generic.
Common issues noted in class and labs
Poor understanding of OOP philosophy
• Function overloading
• Function templates
Special cases of
overloading
• Class templates
Function overloading
int main()
{
NO… why not? std::cout << MyMessage(1) << "\n";
}
Function
• Function scope only begins std::string MyMessage(int msg) {
scope starts
after the function call in main. if (msg == 1) return "Howzit!";
here
return "Hello World!";
}
• What are the two ways to fix
this?
Towards function overloading…
Function prototypes
#include <iostream>
#include <string>
• Will this compile?
std::string MyMessage(int msg) { Function
if (msg == 1) return "Howzit!"; in scope
YES return "Hello World!";
}
int main()
• Function is in scope at the call {
std::cout << MyMessage(1) << "\n";
}
Towards function overloading…
Function prototypes All prototypes
• This too will work… #include <iostream>
• Prototype declares function #include <string>
near the top of the file std::string MyMessage(int); Function in
scope
int main()
• Prototype therefore gives {
function “file” scope std::cout << MyMessage(1) << "\n";
}
• What is it?
• A prototype without a return type (function name + parameter type list)
• Implications
• Function name need not be unique anymore
• Function signature must be unique
• Signatures can only differ in the number and type of parameters
Towards function overloading…
Function signatures
• Example
Function definition
double addNum(int a, double b) { return a + b; }
Function prototype
double addNum(int, double);
Function signature
addNum(int, double)
Function call
std::cout << "Sum of 6 + 4.56 = " << addNum(6,4.56) << std::endl;
Towards function overloading…
Function signatures
Signatures are unique
• Example Therefore the overloading is acceptable
Happy compiler!
int main(){
. This is a special case of overloading
.
.
.
.
What if we had an adjustable
. datatype (like “variant” in VB)
}
template<typename myVar>
myVar addNum(myVar a, myVar b) { return a + b; }
or by…
template<class myVar>
myVar addNum(myVar a, myVar b) { return a + b; }
Towards function overloading…
Function templates
#include <iostream>
template<typename myVar>
myVar addNum(myVar a, myVar b) { return a + b; }
int main()
{
int a = 650, b = 430;
std::cout << "Int sum of 650 + 430 = " << addNum(a,b) << std::endl;
int main(){
std::cout << "Sum of 65 + 43.56 = " << addNum(65, 43.56) << std::endl;
std::cout << "Sum of 65 + 43.56 = " << addNum(43.56, 65) << std::endl;
}
Towards function overloading…
Function templates - notes
used used