Cplusplus OOP
C++ and OOP
- Function Overloading & Default Parameters
- Arguments By Reference
- cin / cout
- Inline Functions
- Memory Allocation
- Additional Improvements
- Introduction to OOP C++
- Overloading functions & operators
- Classes & Objects
- Inheritance & Polymorphism
- Templates & STL
- Introduction to OOD
Function Overloading
- We would like to avoid writing / knowing / using a huge number of functions which, in effect, do the same action.
- It is possible to define numerous functions with the same name, as long as the compiler can detect (while calling the function, according to its arguments), which function should be used
void printNice(int i); void printNice(int i, char ch); void printNice(int i, char* str); void printNice(float f);
Input and Ouput (cin, cout)
I/O in C
- When using printf (or scanf), the programmer must define the type of each argument.
- We could write a different function for each type…
I/O in C++
- We can use the I/O objects cin and cout (defined in <iostream.h>)
- We will use the operators “<<“ and “>>”
- Thanks to function overloading, there is no need to define the type of the arguments.
Output
#include <iostream.h> void main( ){ int i = 23; char *str = “hello”; cout<<str; cout<<i<<endl; cout<<“the value of i is “<<i<<endl; cout<<(char)65; }
Input
#include <iostream.h> void main( ){ int age; char str[100]; cout<<“Please enter your name”; cin>>str; cout<<“Please enter your age”; cin>>age; }
Classes and Objects
- A class represents a data entity.
- Classes could be regarded as new types, just like the fundamental types: int, float, chart, etc.
A class is defined (declared) and used as follows: |
|
class MyClass { [private:] variables (data members) … functions (methods) … public: variables (data members) … functions (methods) … }; |
void main(){ // define objects of type // class_name MyClass MyObject1; MyClass MyObject2; // call a member function MyObject1.func1(…); // assign value to data members MyObject1.Index = 12; } |
Example |
|
class CPoint { int m_x , m_y; public: void Init() { m_x = 0; m_y = 0; } void Set(int ax, int ay) { m_x = ax; m_y = ay; } void Print() { cout<<"x = "<<m_x<<", y = "<<m_y<<endl; } }; |
#include <iostream.h> void main() { CPoint p1, p2; p1.Init(); p2.Set(4,6); p1.Print(); p2.Print(); } |
Data Members
- Data Members vs. Function variables
- Private and public permissions
- Objects as Data Members
Data Members vs. Function variables
- Member functions “know” all the data members of the same object.
- When activating a member function of a specific object, it can operate on the data members of that object.
- Unlike local variables (that “live” only until the function terminates) the data members are alive as long as the object is alive.
- If we keep on sending the same variable to many method of the class,
this may be a good sign that this variable should be a member data.
Private and Public Permissions
- Members (data & functions) can have either a public or a private permission.
- Public members can be accessed at any point in the code (if you have access to the object they are in).
- Private members can be accessed only by member functions of that class.
- The permissions can be set using the keywords “public:” and “private:” and will apply until the next occurrence of public:/private: .
- The default permission of a class is private.
- Permissions can be altered as many time as we want.
Why private?
Prohibiting direct access to the data members by a programmer using the class.
How to access private data members?
- Get and Set functions
- ByRef return value..
Data Members
class DPoint { int x; int y; private: init() { x = 0; y = 0; } };
Classes Vs. Structs
- A struct is a class whose default permission is public (reminder: the default permission in a class is private).
- The use of structs in C++ is scarce.
- They will be mainly used to define data collections with no methods (very similar to their usage in C).
Objects as Data Members
- Data members can also be objects.
Example
Why have we used pointers in the CTeacher example? Why not using object data members?
- B holds an object of type A -> put A before B
- B holds an object of type A and A holds an object of type B -> ???
- B points to an object of type A -> put A before B, or declare A before B
- B points to an object of type A and A points to an object of typeB -> put A before B and declare B before A
Can a class hold a data member of the same class? Can a class hold a pointer to an object of the same class?
Objects as function arguments
When sending an object as a function argument:
- It preferred to send it ByRef(efficiency)
- If the function should not change the object --add "const".
Pointers to objects
- In an analogue manner to the definition of pointers to fundamental data type in C
(i.e. int *pIndex), we can define pointers to objects (i.e. CPoint *pMyPoint).
- Important: Pointers to objects do not necessarily represent real objects.
We should:
- Assign it with a pointer to an existing object, or…
- allocate a new object to this pointer.
- Example: pmain
- What about memory allocation and release of data members?
Methods (Member functions)
- Member Functions vs. Global Functions
- The "this" pointer
Member Functions vs. Global Functions
Member functions (methods) represent the services each class offers. They operate on the data members of the object and can be accessed only through the object.
- encapsulation
- modularity
Global functions will be used for general purpose operations that cannot be assigned to any specific class.
- Examples? How about:
If we keep on sending an object of the same class to a global function, this may be a good sign that this function should be a method.
Methods (Member functions)
Using the pointer "this"
- If we keep on sending an object of the same class to a global function, this may be a good sign that this function should be a method.
- The method can use the pointer “this”, which points to the operating object.
- Sending the object to a different function…
- Returning the object as return value…
External Function Implementation
- Functions that are being implemented inside the class definition are automatically defined as inline functions.
- Loops or otherwise complicated functions are not appropriate.
- Inline function should be used only for simple functions
- Most functions should be implemented externally.
- Within the class definition we shall only include their prototypes.
- To indicate that a function implementation is a member function, we can use the scope resolution operator “::” .
Methods (Member functions) working with multiple files
Most classes will be implemented in two files:
- header file (.h)-class definition: data members and prototypes.
- code file (.cpp) -a collection of function implantation.
cpoint.h | cpoint.cpp | main.cpp |
class CPoint { int m_x , m_y; public: void Init(); bool Set(int ax, int ay); void Print(); int GetX() { return m_x; } int GetY() { return m_y; } }; |
#include “cpoint.h” void CPoint::Init() { … } bool CPoint::Set(int ax, int ay) { … } |
#include “cpoint.h” #include “crectangle.h” … void main() { CPoint P1; … } |
Object Size and Local Objects
- The object size is the sum of all sizes of its data members.
- (member functions do not affect the object size). Why?
- The operator sizeof can be applied to both classes and objects:
sizeof(CPoint) -> sizeof(int + int) sizeof(P1) -> the same sizeof(CRectangle) -> sizeof(CPoint + CPoint + char) sizeof(R1) -> the same
Local Objects
- Local objects (which were defined within a function), die when the function terminates (just like local variables).
- Local objects can be used though as ByVal return-values (since a copy of it will be created on the stack).
Global Objects
- Objects which are defined externally (outside the main function) will be global objects (just like global variables).
- Global object will be deleted only after the main function terminates.
Constructor and Destructor Function
Constructor Functions
- As we all know, when variables are defined, they may initially contain garbage values.
- The same is true for class data members.
- Although Init() or Set() functions can be used, there is no guarantee that they will be called before using the object.
Garbage values can cause severe problems:
- Reminder: CPoint class
- Using a variable before it was initialized…
- Using POINTERS before allocating memory!!!
What Constructor Function
- The Constructor (C’tor) function can solve the problem described in the previous slide.
- The Constructor function is called automatically when the object is created.
- Object Creation--> Memory Allocation --> Constructor Activation
Constructor Can
- Initialize variables
- Allocate memory
- Perform any action we wish to take before starting working with the object.
Constructor Name
- The name of the Constructor function is the same to the name of the class.
- Constructor function defines in the public section.
- The Constructor function can not return value and should not define a void return value either.
Example 1
class Example{ public: Example(int x = 0):x(myX){} ; // use initialization list private: int myX; }; Example example3(5); // ok Example example3 = 5; // ok
Example 2
#include <iostream> using namespace std; class CRectangle { int width, height; public: CRectangle (); CRectangle (int,int); int area (void) {return (width*height);} }; CRectangle::CRectangle () { width = 3; height = 3; } CRectangle::CRectangle (int a, int b) { width = a; height = b; } int main () { CRectangle rect (3,4); CRectangle rectb; cout << "rect area: " << rect.area() << endl; cout << "rectb area: " << rectb.area() << endl; return 0; }
Out put
12 9
Initialize Line for data members
- The object data members can be initialized even before entering the Constructor function body using an initialization line.
- An initiation line guarantees that when we enter the Constructor function's body, the variables are already initialized.
- Even we have already initialized the data members and there is nothing left for the Constructor function to do, it should still defined. (i.e simply add{}).
- The initialization line is considered part of the function and should thus be written where the function is implemented (rather than in the prototype).
- The order of parameters in the initialized line is not mandatory.
- An initialization line must be used if: The object includes an object data member that does not have a default constructor.
- The Constructor function of the object will be called only after all the data members have been created.
- The Constructor of the data members will be activated before the Constructor of the object itself.
- The initialization line must be used also if: Const variables (i.e const int zero=0;) and Reference variable.
Example 1
Destructor Function
- The Destructor function is responsible for any actions we wish to do just before the object is terminated: Free allocated memory… and other actions we wish to perform…
- Local object termination (when exiting the block where it was defined)…
- Deletion of a dynamically allocated object…
- Global object deletion at the end of the application…
Destructor Name
- The name of the Destructor function is similar to the name of the class with the prefix “~”.
- Destructor functions should (obviously) be defined as public.
- A destructor cannot return a value and doesn’t get any arguments. It cannot be overloaded either. WHY?
Object Life Cycle
- Object Creation--> Memory Allocation -->Constructor Activation
- Destructor Activation-->Memory Release --> Object Deletion
Copy Constructor Function
- As we saw in the last lecture, when copying one object to the other, all data members are copied as is.
- If the object includes data members that are pointers, we will get dual pointing:
- Changing the data member in one object may change the data member in the copied object…
- We may try to free the same allocated memory twice!!!
- There are cases when we wish to modify additional data members when an object is copied. (EXAMPLE?)
- We can implement a Copy Constructor which will properly copy an object!!!
Example 1
class X { public: // Constructor for class X X(); // Destructor for class X ~X(); };
Example 2
#include <string> class Y { private: char * name1; int number; public: // Constructor Y(const char*, int); // Destructor ~Y() { delete[] name1; } }; // Define class Y constructor Y::Y(const char* n, int a) { name1 = strcpy(new char[strlen(n) + 1 ], n); number = a; } int main () { // Create and initialize // object of class Y Y yobj = Y("Bob", 10); // ... // Destructor ~Y is called before // control returns from main() }