C++ course 

Lesson 3 recap

Objectives

C++ extra syntax

- Default parameter values

- Function overloading

Object Oriented

- Terminology

- Philosophy

- Programming

- Objects life cycle

- Inheritance

- Access control (public/private/protected)

- Initialisation list

 

 

 

Default parameter values

In C++ it is possible to provide default values to to parameters

void foo(int x = 100); 

int main() {
   
  foo();  // x will default to 100
  foo(17);// x will be 17
}

It is not possible to add a default to a parameter if there are more parameters without default to it's right.

void foo(int x = 100, int y);          // Invalid  
void foo(int x; int y = 100, int z);   // Invalid
void foo(int x; int y = 1, int z = 2); // Valid

It is advisable to only add default's to the declaration(header files) the caller during compilation is supposed to only see the declarations.

Function overloading

In C++ the function signature is combined with the parameters singature

allowing to have multiple functions with the same name 

int add(int a, int b) 
{
   return a + b;
}

double add(double a, double b)
{
   return a + b;
}

Notice: The functions can not differ only on the return value.

Object Oriented

OO - Terminology

// Object Oriented terminology
#include <iostream>
#include <string>

// A class is a new user defined type 
// It is composed of attributes(the data) and methods(the actions that can be performed on the data)
//
// Constructor & Destructor shouldn't be considered as functions as such but rather as 
// Initialization and cleanup.
class Example {
    
   public:   // Access control (Can be private/public/protected) 
   
     Example() {}   // Constructor (aka ctor): has the class name and return no values
     ~Example() {}  // Destructor  (aka dtor): starts with a tilde (~) has the class name and returns no value
   
   int   attr1;   // Attribute or field or member data 
   char* attr2;   
   
   void action1() {} // member function or method

};

int main()
{
    Example e; // e is an object (or instance) of type (or class) Example
   
}

OO - Philosophy 

1.  Abstraction - ability to introduce new types

 

2. Encapsulation

  i. Object Oriented Design forces to encapsulate (pack together) related attributes and actions

   ii. additional compiler directives help the compiler maintain the encapsulation (public / private / protected)

 

 

 

 3. Inheritance - The ability to inherit and specialise behaviour

 

 

 

 4. Polymorphism - To be discussed 

class Mouse { /* ... */ }; // Introduce a new type tiger 
class Mouse { 
   private:  // Enforce encapsulation by preventing the outside seeing internal implementation
       int numberOfTeeth;  

   public:
       void bite();  // A Tiger encapsulates all its actions and attributes
}; 
class MightyMouse : public Mouse { 
  /* ... */
  public:
    void fly();
};

OO - Access modifiers

To allow the programmer to enforce encapsulation, class/struct Access modifiers were introduced.

Public: Allows access to fields and actions to everybody

class AllPublic {
  public: 
     int field1;
     void foo() { /* foo's code */ }
};

/* ... */

AllPublic ap: 
ap.field1 = 1; // Access field1
ap.foo();      // Execute ap's foo method  

Private: Allows access only from the class code itself

class AllPrivate {
  private: 
     int field1;
     void foo() { field1 = 10; } // Legal
};

/* ... */

AllPrivate ap: 
ap.field1 = 1; // Disallowed by compiler 
ap.foo();      // Disallowed by compiler

OO - Primitives

The keyword class introduced to allow creation of structs with functions (methods). Because the functions are part of the structs, the data (attributes) doesn't need to be visible from the outside.

The struct also support the new OO constructs, the difference between for backward computability is that everything is public by default for struct. While for class all is private by default.

                           

                           =                           and                           =  

 

- A struct & class compiled by a C++ compiler will have Constructor & Destructor generated for them.

- A class/struct in C++ is not obliged to have methods nor attributes. In C an empty struct is illegal.

struct A {               
 /* code */
}                    
class A {
 public:             
 /* code */
}                    
struct A {
 private:             
 /* code */
}                    
class A {             
 /* code */
}                    

OO - Life Cycle

C++ object model ensures that a well implemented class will have it's object always in a valid state. To enforce that each object created either on the stack or Heap, passes through a construction.

 

A default constructor is generated by the compiler if there was no constructor supplied by the programmer. 

A Constructor is a function that returns no value and has the same name as it's class.

class Mouse {
  public: 
    Mouse() { /* Construction code */ } // default constructor
    ~Mouse() { /* Destruction code */ }
};

A destructor is called when the object is going out of scope or when a delete is called on an allocated object 

 { 
   Mouse m;
 } // M is going out of scope, destructor called
 
 Mouse* pMouse = new Mouse(); // Memory is allocated and than constructor is called
 delete pMouse;               // Destructor called and than memory is freed.

OO - Inheritance

Inheritance is allowed by publicly inheriting from a another class

public Mouse {};

public MightyMouse : public Mouse {}

Inheritance allows for code reuse to be implicit from one class to the another.

This can also be viewed as specialisation, if the abstraction was done correctly,  than the base class are more generic and the derived class more specific 

OO - Construction sequence

                Output

 

 

 

=>

class Value 
{
  public:
    Value(const string& in_name): name(in_name) 
      { cout << "ctor Value: (" << name << ")" << endl; }
    ~Value() { cout << "dtor Value: (" << name << ")" << endl; }

  private: 
     string name;
};

class Base 
{
  public:
    Base():baseVal("Base")  { cout << "ctor Base:" << endl; }
    ~Base()  { cout << "dtor Base:" << endl; }
    
  private:
    Value  baseVal;
};

class Derived : public Base 
{
  public:
    Derived(): derivedVal("Derived") { cout << "ctor derived: " << endl; }
    ~Derived() { cout << "dtor Derived:" << endl; }
    
  private:
    Value derivedVal;
};

int main() {
  {
      Derived d;
  }
}
ctor Value: (Base)
  ctor Base:
    ctor Value: (Derived)
      ctor derived: 
      dtor Derived:
    dtor Value: (Derived)
  dtor Base:
dtor Value: (Base)

OO - Constructor Initialisation list

Because as we saw in previous slide the initialisation sequence in C++, requires Base's than attributes and than self. 

 

By the time the constructor code is reached it is expected that both Bases and attributes are already constructed.

// Excerpt from previous slide

class Base 
{
  public:
    // Initialisation for baseVal is called before Base constructor
    Base(const string& in_name = "Base"):baseVal(in_name)  
      { /* code */ }  
    ~Base()  { cout << "dtor Base:" << endl; }
    
  private:
    Value  baseVal;
};

class Derived : public Base 
{
  public:
    // Initialisation of both Base and derived takes place before Derived constructor
    Derived():Base("Base of Derived"), derivedVal("Derived") { cout << "ctor derived: " << endl; }
    ~Derived() { cout << "dtor Derived:" << endl; }
    
  private:
    Value derivedVal;
};

c++L03

By perplexedpigmy