C++ Essentials Training
5-day session

 
Overview
Understanding principles of Object Oriented Programming Overview
Understanding the structure of a c++ program
Understanding Polymorphism
Understanding UML modeling
Practical labs with GNU g++ compiler
Duration
Three days - 40 hours (8 hours a day)
50% of lecture, 50% of practical labs.

Trainer
Audience
Professional Software developers
People supporting large scale products.
Prerequisite
Knowledge of C programming
In particular, participants must be familiar with creating and dealing with
complex data types and structures, with pointers to such symbols, as well as
with function pointers.
Advance C training agenda is available at
http://www.minhinc.com/training/c/advance-c-slide.php
and can be downloaded from
http://www.minhinc.com/training/advance-c-slide.pdf

Knowledge of Object Oriented Concepts
Oops concept like Abstraction, Inheritance, Polymorphism would help.

Setup
Linux machine with GNU g++ compiler installed.
© www.minhinc.com
p1
Lecture
Lecture session will be course content presentation through the trainer.
Any source code example related to the topic will be demonstrated, it would
include executing the binaries.
Complete lecture material can be downloaded from
http://www.minhinc.com/training/advance-cpp-slides.pdf
Labs
Labs session would be completely hands on session where each example
(with example data and execution instruction) would be provided to the
students. Students can verify their results with the results provided in
the material.
Day 1 Morning

© www.MinhInc.com
p2
Day 1 Afternoon

     Lab
Day 2 Morning

Day 2 Afternoon

     Lab
© www.MinhInc.com
p3
Day 3 Morning

Day 3 Afternoon

     Lab
Day 4 Morning

© www.MinhInc.com
p4
Day 4 Afternoon

     Lab
Day 5 Morning

© www.MinhInc.com
p5
Day 5 Afternoon

     Lab
© www.MinhInc.com
p6
 
Day 1 Morning
  1. Introduction


             Stages of Program Development    |
                                              |
                                              v
                                   ----------------------
                                   | Architecture design|
                                   ----------------------
                                              |
                                              v
                                   ----------------------
            ---------------------->| Detailed design    |
            |                      ----------------------
            |                                 |
    -------------------                       v
    |  Redefine design|             ---------------------
    -------------------      ------>| Edit source files |
            ^                |      ---------------------
            |                |                |
            |                |                v
            |                |      ----------------------
            |                |      | Compile source file|
            |                |      ----------------------
            |                |                |
            |                |                v
            |                |       --------------------
            |                |       | Link Object files|
            |                |       --------------------
            |                |                |
            |                |                v
            |                |       ---------------------
            |                |       | Test and debug    |
            |                |       | executable program|
            |                |       ---------------------
            |                |                |
            +---------------------------------+
Architecture of c program
Function consists of header and body
 - Header contains preprocessor statements and class declarations (except template inclusion case where source is also included)
 - Body, enclosed in {brackets} contains statements, each terminated by semicolon

One function must be one called main()
 - C start up code calls main function as the entry point in the program.

Global variables are initialized prior the entry to main function.

Program execution starts in main, and progresses, statement by statement, until the last statement in main is completed

Definition of variable class and functions put in source file.
A source file contains definition of variable and functions.

<<source.c>>
extern int i; // declaration
int func(); // declaration
int i=10;//declaration and definition
int func(){//definition
}

Compiling one source file needs only declarations of the variable and the function be visible. Definition is not required while generating object file.

$ cat source.c
#include <stdio.h>

int func();
int main(){
© www.minhinc.com
p7
func();
return 0;
}
$ g++ -c source.c -o source.o <-- compiling without definition
$ nm source.o
                 U _Z4funcv <--- U is undefined
                 U __gxx_personality_v0
0000000000000000 T main

Day 1 Morning
  1. Introduction

Header contains constants, macros, system wide global variables, preprocessor
statements and declarations.

Header file is included with #include
example

$ cat header.h
#ifndef HEADER_H
#define HEADER_H
#include <stdio.h>
const int i=10;
extern int j;
struct A{
};
void put_s(const char*);
#endif

$cat source1.c
#include "header.h"
void put_s(const char *cp){
printf("puts %s
",cp);
}

$cat source2.c
#include "header.h"
int j=15;

$cat main.c
#include "header.h"
int main(int argc, char *argv[]){
puts("hello world");
printf("j %d
",j);
return 0;
}

$ g++ source1.c source2.c main.c -o headersource
$ ./headersource
hello world
j 15

Day 1 Morning
  1. Introduction

A file that contains compiled code is known as an object file. Compiler creates object file which is binary file.  It is of three types

a) Relocatable file
© www.minhinc.com
p8
This type of object file contains data and code that can be linked together with other relocatable files to produce an executable binary or a shared object file. It is similar as the .o file produced when we compile a code the following way :

$gcc -Wall -c test.c -o test.o
So the test.o produced after the operation above would be a relocatable file.

$ nm mathoperation.o

0000000000000000 T add
0000000000000027 T div
                 U fixit <-- Undefined
0000000000000014 T mul

$ objdump -x mathoperation.o

mathoperation.o:     file format elf64-x86-64
mathoperation.o
architecture: i386:x86-64, flags 0x00000011:
HAS_RELOC, HAS_SYMS
start address 0x0000000000000000

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .text         0000005a  0000000000000000  0000000000000000  00000040  2**2
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
  1 .data         00000000  0000000000000000  0000000000000000  0000009c  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          00000000  0000000000000000  0000000000000000  0000009c  2**2
                  ALLOC
  3 .comment      0000002e  0000000000000000  0000000000000000  0000009c  2**0
                  CONTENTS, READONLY
  4 .note.GNU-stack 00000000  0000000000000000  0000000000000000  000000ca  2**0
                  CONTENTS, READONLY
  5 .eh_frame     00000078  0000000000000000  0000000000000000  000000d0  2**3
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
SYMBOL TABLE:
0000000000000000 l    df *ABS*	0000000000000000 mathoperation.c
0000000000000000 l    d  .text	0000000000000000 .text
0000000000000000 l    d  .data	0000000000000000 .data
0000000000000000 l    d  .bss	0000000000000000 .bss
0000000000000000 l    d  .note.GNU-stack	0000000000000000 .note.GNU-stack
0000000000000000 l    d  .eh_frame	0000000000000000 .eh_frame
0000000000000000 l    d  .comment	0000000000000000 .comment
0000000000000000 g     F .text	0000000000000014 add
0000000000000014 g     F .text	0000000000000013 mul
0000000000000027 g     F .text	0000000000000033 div
0000000000000000         *UND*	0000000000000000 fixit

RELOCATION RECORDS FOR [.text]:
OFFSET           TYPE              VALUE
000000000000004d R_X86_64_PC32     fixit-0x0000000000000004

RELOCATION RECORDS FOR [.eh_frame]:
OFFSET           TYPE              VALUE
0000000000000020 R_X86_64_PC32     .text
0000000000000040 R_X86_64_PC32     .text+0x0000000000000014
0000000000000060 R_X86_64_PC32     .text+0x0000000000000027

$ cat mathoperation.c

void fixit(int,int);
int add(int a,int b){
return a+b;
}
int mul(int a,int b){
return a*b;
}
int div(int a,int b){
if (b=0)fixit(a,b);
return a/b;
}

b) Shared object file
This type of object file is used by the dynamic linker to combine it with the executable and/or other shared object. It is similar as the .so file produced when the code is compiled with the -fPIC (position independent code) flag in the following way :

$gcc -c -Wall -Werror -fPIC shared.c -o shared.o
$gcc -shared -o libshared.so shared.o

A shared object file libshared.so is produced as output.

example.
$gcc -c -fPIC mathoperation.c -o mathoperation.o

$ nm mathoperation.o
0000000000000000 T add
0000000000000027 T div
                 U fixit
                 U _GLOBAL_OFFSET_TABLE_ <- relocating table
0000000000000014 T mul

$ gcc -c -fPIC mathoperation.c -o mathoperation.o
$ gcc -shared -o libmathoperation.so mathoperation.o
$ ldd libmathoperation.so

	linux-vdso.so.1 =>  (0x00007fffbd5fe000)
© www.minhinc.com
p9
	libc.so.6 => /lib64/libc.so.6 (0x00007ffd916b4000)
	/lib64/ld-linux-x86-64.so.2 (0x00007ffd91c8b000)

$ nm libmathoperation.so

0000000000000708 T add
0000000000201030 B __bss_start
0000000000201030 b completed.6333
                 w __cxa_finalize@@GLIBC_2.2.5
0000000000000620 t deregister_tm_clones
000000000000072f T div
0000000000000690 t __do_global_dtors_aux
0000000000200e00 t __do_global_dtors_aux_fini_array_entry
0000000000200e10 d __dso_handle
0000000000200e18 d _DYNAMIC
0000000000201030 D _edata
0000000000201038 B _end
0000000000000764 T _fini
                 U fixit
          <--------- Undefined
00000000000006d0 t frame_dummy 0000000000200df8 t __frame_dummy_init_array_entry 0000000000000840 r __FRAME_END__ 0000000000201000 d _GLOBAL_OFFSET_TABLE_ w __gmon_start__ 00000000000005b8 T _init w _ITM_deregisterTMCloneTable w _ITM_registerTMCloneTable 0000000000200e08 d __JCR_END__ 0000000000200e08 d __JCR_LIST__ w _Jv_RegisterClasses 000000000000071c T mul 0000000000000650 t register_tm_clones 0000000000201030 d __TMC_END__


c) Executable file
This type of object file is a file that is capable of executing a program when run.

$ gcc -Wall test.c -o test
Tool - objdump, nm

Example -
<<main.c>>
#include "sample.h"
int main(int argc, char *argv[]){
struct fraction frtn;
frtn.numerator=12;
frtn.denominator=5;
func(&frtn);
return 0;
}

<<sample.c>>
#include <stdio.h>
#include "sample.h"
void func(struct fraction *f){
printf("value %d
",f->numerator/f->denominator);
}

<<sample.h>>
#ifndef SAMPLE_H
#define SAMPLE_H
struct fraction {
int numerator;
int denominator;
};
void func(struct fraction *f);
#endif

$ objdump -r sample.o
sample.o:     file format pe-i386

RELOCATION RECORDS FOR [.text]:
OFFSET   TYPE              VALUE
0000001b dir32             .rdata
00000020 DISP32            _printf


RELOCATION RECORDS FOR [.eh_frame]:
OFFSET   TYPE              VALUE
00000020 DISP32            .text


$ nm sample.o
00000000 b .bss
00000000 d .data
00000000 r .eh_frame
00000000 r .rdata
00000000 r .rdata$zzz
00000000 t .text
00000000 T _func
          U _printf

© www.minhinc.com
p10
$ ldd a.out
linux-vdso.so.1 =>  (0x00007fffffbfe000)
libc.so.6 => /lib64/libc.so.6 (0x00007f96f51ee000)
/lib64/ld-linux-x86-64.so.2 (0x00007f96f55c3000)

Day 1 Morning
  1. Introduction

Declaration - Asserts the existence of a variable, function or type defined elsewhere in the program. A variable may be declared by preceding its type with the keyword extern.

int a; // just declaration
void func();//just declaration

c++
int a // declaration and definition
extern a // declaration

- Declaration can be made multiple times.

Definition - Allocates storage for a variable of a specified type and  optionally initializes the variable.

int a=10; //declaration and definition
void func(){// declaration and definition
}

- Definition must be only once.
- How are declarations written so that variables are properly declared during compilation?
- How are declarations arranged so that all the pieces will be properly connected when the program is loaded?
- How are declarations organized so there is only one copy?
- How are external variables initialized?

Day 1 Morning
  1. Introduction

---------------  ---------------  --------------- ---------------
|source file  |  | source file |  | source file | | source file |
---------------  ---------------  ---------------  --------------
      |                 |                |               |
      v                 v                v               v
---------------  ---------------  --------------- ---------------
| object file |  | object file |  | object file |  | object file|
---------------  ---------------  ---------------  --------------
      |                 |               |               |
      |                 |               |               |
      |                 |               |               |
      |                 |               |               |
      |                 v    +----------+               |
      |                . . . v                          |
      |              .       .<-------------------------+
      +------------->. link  .  <------------     +--------+
                       . . .                |     | Runtime|
© www.minhinc.com
p11
                         |                  +-----| Library|
                         v                        +--------+
                  ---------------
                  | Executable  |
                  |    Code     |
                  ---------------

Preprocessor - It is a program that runs as part of compilation of a c program.  It is not part of compiler. In simplistic terms, a C Preprocessor is just a text substitution tool and they instruct compiler to do required preprocessing before actual compilation.
All preprocessor commands begin with a pound symbol (#). It must be the first non blank character, and for readability, a preprocessor directive should begin in first column. Following section lists down all important preprocessor directives:

Directive              Description
#define                Substitutes a preprocessor macro
#include               Inserts a particular header from another file
#undef                 Undefines a preprocessor macro
#ifdef                 Returns true if this macro is defined
#ifndef                Returns true if this macro is not defined
#if                    Tests if a compile time condition is true
#else                  The alternative for #if
#elif                   #else an #if in one statement
#endif                 Ends preprocessor conditional
#error                 Prints error message on stderr
#pragma                Issues special commands to the compiler, using


Tool - cpp

$ cat test.h
#ifndef TEST_H
#define TEST_H
int func():
#endif
$ cat test.cpp
#include "test.h"
int main(){
return 0;
}

$ cpp test.cpp
# 1 "test.cpp"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "test.cpp"
# 1 "test.h" 1

int func():
# 2 "test.cpp" 2
int main(){
return 0;
}

Compiling Source Files
Once your program is written in C, it is ready to be translated into a  machine-readable language.
A compiler translates C statements into machine statements
- A compiler creates object code, which is an intermediary step between source code and final executable code
- The compiler checks for syntax errors; e.g., Missing punctuation
- The compiler performs simple optimization on your code; e.g., eliminate a redundant statement

Tool - gcc

Linking Object Files
- The linker links together all object modules to form an executable image of the program
- The output of the linker is an executable image, which can be loaded into memory and executed
- The linker resolves any references to library functions
 - If your program uses a library routine, like sqrt, the linker finds the object code corresponding to this routine and links it within the final executable image
© www.minhinc.com
p12
- The linker is automatically invoked by the compiler

Loading Your Program
The loader loads your program into the computer's memory
On most systems, this is performed automatically by the operating system
when you run the program
Most embedded systems require you to explicitly run a loader program
to get the program into memory

Tool - gcc

Day 1 Morning
  1. Introduction

Executable file format which once loaded by a suitable executable loader, can be directly Executed by the CPU rather than become interpreted by software.
In addition to the binary application code, the executable may contain headers and tales with relocation and fix up information as well as various kinds of meta data.
ELF(Executable and Linkable File Format) - unix/linux
COFF(Command Object File Format) - windows
PE - windows
MZ - DOS
Mach-O (mac OS and iOS)

ELF Header

#define EI_NIDENT 16
typedef struct {
e_ident[EI_NIDENT];
unsigned char e_type;
Elf32_Half e_machine;
Elf32_Half e_version;
Elf32_Word e_entry;
Elf32_Addr e_phoff;
Elf32_Off e_shoff;
Elf32_Off e_flags;
Elf32_Word e_ehsize;
Elf32_Half e_phentsize;
Elf32_Half e_phnum;
Elf32_Half e_shentsize;
Elf32_Half e_shnum;
Elf32_Half e_shstrndx;
} Elf32_Ehdr;

 1. e_ident
 In order to support all this the initial information in ELF file contains information
 on how to interpret the file independent of the processor on which the executable is running.
 Name     Value      Purpose
 EI_MAG     0          File identification
 EI_MAG1    1          File identification
 EI_MAG2    2          File identification
 EI_MAG3    3          File identification
 EI_CLASS   4          File class
 EI_DATA    5          Data encoding
 EI_VERSION 6          File version
 EI_PAD     7          Start of padding bytes
 EI_NIDENT  16         Size of e_ident[]

    EI_MAG The first four bytes above hold the magic number 0x7fELF
    EI_CLASS An ELF can have two classes, 32 bit or 64 bit. This makes the file format portable.
    EI_DATA This member gives the information on data encoding, big endian or little endian format.
    EI_VERSION This member provides information on object file version.
    EI_PAD This member marks the start of unused bytes in the e_indent array of information.
    EI_NIDENT This member provides the size of array e_indent. This helps in parsing the ELF file.

 2. e_type
 This member identifies the type of object file. For example, an object file can be of
  following types :
 Name    Value    Meaning
 ET_NONE  0       No file type
 ET_REL   1       Relocatable file
 ET_EXEC  2       Executable file
 ET_DYN   3       Shared object file
 ET_CORE  4       Core file
 NOTE: The above list is not exhaustive but still gives information on main object
  file types that ELF can refer to.

 3. e_machine
 This member gives information on architecture that an ELF file requires.
 Name            Value      Meaning
 ET_NONE           0          No machine
 EM_M32            1          AT&T WE 32100
 EM_SPARC          2          SPARC
 EM_386            3          Intel Architecture
 EM_68K            4          Motorola 68000
 EM_88K            5          Motorola 88000
 EM_860            7          Intel 80860
 EM_MIPS           8          MIPS RS3000 Big-Endian
 EM_MIPS_RS4_BE   10          MIPS RS4000 Big-Endian
 RESERVED       11-16         Reserved for future use

 4. Additional Members
 Apart from the above three members, it also has the following members:
 e_version: Provides the ELF object file version information.
 e_entry: Provides the virtual address information of the entry point to which
  the system must transfer the control so that the process can be initiated.
© www.minhinc.com
p13
 e_phoff: Holds the offset to program header table. This information is stored in
  terms of bytes. In absence of a program header table, the information
  contained by this member is zero.
 e_shoff: Holds the offset to section header table. As with e_phoff, this
  information too is stored in form of bytes and in absence of a section
  header table, the information contained by this field is zero.
 e_flags: Holds information related to process specific flags.
 e_ehsize: Holds information related to ELF header size in byes.
 e_phentsize: Holds information related to size of one entry in the object
  file's program header table. Note that all the entries are same in size.
 e_phnum: Holds the information related to number of entries in program header table.
 e_shentsize: Holds the information related to size of one entry in the
  section header table. The size is represented in form of number of bytes.
 e_shnum: Gives the information related to the number of entries in the section header table.

Tool - readelf used to list the object data
main() {
  printf("Hello World
");
}

$ readelf -h hello.o

ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              REL (Relocatable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          0 (bytes into file)
  Start of section headers:          312 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           0 (bytes)
  Number of program headers:         0
  Size of section headers:           64 (bytes)
  Number of section headers:         13
  Section header string table index: 10


$ readelf -S hello.o

There are 13 section headers, starting at offset 0x138:
Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .text             PROGBITS         0000000000000000  00000040
       0000000000000015  0000000000000000  AX       0     0     4
  [ 2] .rela.text        RELA             0000000000000000  00000598
       0000000000000030  0000000000000018          11     1     8
  [ 3] .data             PROGBITS         0000000000000000  00000058
       0000000000000000  0000000000000000  WA       0     0     4
  [ 4] .bss              NOBITS           0000000000000000  00000058
       0000000000000000  0000000000000000  WA       0     0     4
  [ 5] .rodata           PROGBITS         0000000000000000  00000058
       000000000000000c  0000000000000000   A       0     0     1
  [ 6] .comment          PROGBITS         0000000000000000  00000064
       000000000000002e  0000000000000001  MS       0     0     1
  [ 7] .note.GNU-stack   PROGBITS         0000000000000000  00000092
       0000000000000000  0000000000000000           0     0     1
  [ 8] .eh_frame         PROGBITS         0000000000000000  00000098
       0000000000000038  0000000000000000   A       0     0     8
  [ 9] .rela.eh_frame    RELA             0000000000000000  000005c8
       0000000000000018  0000000000000018          11     8     8
  [10] .shstrtab         STRTAB           0000000000000000  000000d0
       0000000000000061  0000000000000000           0     0     1
  [11] .symtab           SYMTAB           0000000000000000  00000478
       0000000000000108  0000000000000018          12     9     8
  [12] .strtab           STRTAB           0000000000000000  00000580
       0000000000000013  0000000000000000           0     0     1
The readelf program is capable of performing disassembly:

$ readelf -i 1 hello.o

0x00000000  pushl       %ebp
0x00000001  movl        %esp,%ebp
0x00000003  pushl       $0x0
0x00000008  call        0x08007559
0x0000000d  addl        $4,%esp
0x00000010  movl        %ebp,%esp
0x00000012  popl        %ebp
0x00000013  ret

The .rel.text section contains the re-locations for the .text section of
the file, and we can display them as follows:

$ readelf -r hello.o

Relocation section data:.rel.text (0x2 entries)
Tag: 00004 Value 00301 R_386_32    (0 )
Tag: 00009 Value 00b02 R_386_PC32  (0 printf)

$ readelf -l hello

Elf file type is EXEC (Executable file)
Entry point 0x400440
There are 9 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000400040 0x0000000000400040
                 0x00000000000001f8 0x00000000000001f8  R E    8
  INTERP         0x0000000000000238 0x0000000000400238 0x0000000000400238
                 0x000000000000001c 0x000000000000001c  R      1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
© www.minhinc.com
p14
                 0x0000000000000714 0x0000000000000714  R E    200000
  LOAD           0x0000000000000e10 0x0000000000600e10 0x0000000000600e10
                 0x0000000000000224 0x0000000000000228  RW     200000
  DYNAMIC        0x0000000000000e28 0x0000000000600e28 0x0000000000600e28
                 0x00000000000001d0 0x00000000000001d0  RW     8
  NOTE           0x0000000000000254 0x0000000000400254 0x0000000000400254
                 0x0000000000000044 0x0000000000000044  R      4
  GNU_EH_FRAME   0x00000000000005ec 0x00000000004005ec 0x00000000004005ec
                 0x0000000000000034 0x0000000000000034  R      4
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     10
  GNU_RELRO      0x0000000000000e10 0x0000000000600e10 0x0000000000600e10
                 0x00000000000001f0 0x00000000000001f0  R      1

Section to Segment mapping:
Segment Sections...
   00
   01     .interp
   02     .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
   03     .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss
   04     .dynamic
   05     .note.ABI-tag .note.gnu.build-id
   06     .eh_frame_hdr
   07
   08     .init_array .fini_array .jcr .dynamic .got

Day 1 Morning
  1. Introduction

Unix/Linux process virtual address space

high address -----------------------------
             |                           |    command line arguments
             |                           |  /  and environment
             -----------------------------
             |           stack           |
             - - - - - - - - - - - - - - -
             |             |             |
             |             |             |
             |             v             |
             |                           |
             |                           |
             |                           |
             |             ^             |
             |             |             |
             |             |             |
             - - - - - - - - - - - - - - -
             |           heap            |
             -----------------------------
             | uninitialized data        |  initialized to
             |          (bss)            | / zero by exec
             ----------------------------+
             | initialized data          |   read from
             -----------------------------   | program line
             |            text           |  / by exec
low address  |                           | /
             +---------------------------+

When an executable program is read into system memory by the kernel and executed, it becomes a process. We can consider system memory to be divided into two distinct regions.

One is user space, and the other is kernel Space. Every process has is own user space (about 2GB virtual space,32bit) and are prevented from interfering with one another. The mode change which is from user mode to kernel mode is called a context switch.

         -----------------
         |  Kernel Space |<----+
         |               |     |
         +---------------+     | context switching
         |               |     |
         | User Space    |<----+
         +---------------+

Text, Data and Stack.
The user process is divided into three segments or regions, they are: text, data and stack.

Text Segment.
© www.minhinc.com
p15
The Text segment (a.k.a the Instruction segment) contains the executable program code and constant data. The text segment is marked by the operating system as read- only and can not be modified by the process.  Multiple processes can share the same text segment. Processes share the text segment if a second copy of the program is to be executed concurrently. Sharing can be turned off by using the -N option on the compile time.

Data Segment.
The data segment, which is contiguous (in a virtual sense) with the text segment, can be subdivided into initialized data (e.g. in C/C++, variables that are declared as static or are static by virtual of their placement) and uninitialized (or 0-initialized data. The uninitialized data area is also called BSS (Block Started By Symbol).

Heap Segment
During its execution lifetime, a process may request additional data segment space. Library memory allocation routines (e.g., new, malloc, calloc, etc.) in turn make use of the system calls brk and sbrk to extend the size of the data segment. The newly allocated space is added to the end of the current uninitialized data area. This area of available memory is also called "heap".

Stack Segment.
The stack segment is used by the process for the storage of automatic identifier, register variables, and function call information. The stack grows towards the uninitialized data segment.

The u area.
In addition to the text, data, and stack segment, the OS also maintains for each process a region called the u area (User Area). The u area contains information specific to the process (e.g. open files, current directory, signal action, accounting information) and a system stack segment for process use.  If the process makes a system call (e.g., the system call to write in the function in main ), the stack frame information for the system is stored in the system stack segment. Again, this information is kept by the OS in an area that the process doesn't normally have access to. Thus, if this information is needed, the process must use special system call to access it.  Like the process itself, the contents of the u area for the process are paged in and out bye the OS.

Process Memory Addresses.
The system keeps track of the virtual addresses associated with each user process segment. This addresses information is available to the process and can be obtained by referencing the external variables etext, edata, and end. The addresses (not the contents) of these three variable correspond respectively to the first valid address above the text, initialized data, and uninitialized data segments.

#include <iostream>
extern int etext, edata, end;
using namespace std;
int main( ){
cout << "Adr etext: " << hex << &etext << "	 ";
cout << "Adr edata: " << hex << &edata << "	 ";
cout << "Adr end: " << hex << &end << "
";

char *s1 = "hello"; //in initialized data segmenta
static int a=1; //in initialized data segment
static int b; //in uninitialized data segment
char s2[] = "hello"; //in the stack area.
int * c = new int;

cout <<hex << s1 << endl;
cout <<hex << &a << endl;
cout <<hex << &b << endl;
cout <<hex << s2 << endl;
cout <<hex << c << endl;
delete c;
return 0;
}

$g++ add.cpp
$./a.out
Adr etext: 0x400e4d     Adr edata: 0x602090     Adr end: 0x6021c0
© www.minhinc.com
p16
hello
0x60208c
0x6021b8
hello
0X23ce010

Day 1 Morning
  1. Introduction

A static library is set of object files that were copied into a single file. The static file is created with the archiver (ar).

<<calc_mean.c>>
//#include <stdio.h>
double mean(double a, double b) {
return (a+b) / 2;
}

<<calc_mean.h>>
double mean(double, double);

Creating the static library
First, calc_mean.c is turned into an object file:

$gcc -c calc_mean.c -o calc_mean.o

Then, the archiver (ar) is invoked to produce a static library (named libmean.a) out of the object file calc_mean.o.

$ar  rcs libmean.a      calc_mean.o

Note: the library must start with the three letters lib and have the suffix .a.

$cat calc.c
#include <stdio.h>
#include "calc_mean.h"
int main(){
printf ("mean of 3, 6 is %f
",mean(3,6));
return 0;
}

$ gcc -c calc_mean.c -o calc_mean.o
$ ar cr libmean.a calc_mean.o
$ gcc -c calc.c -o calc.o
$ gcc -o calc calc.o -L. -lmean
$ ./calc

mean of 3, 6 is 4.500000

$ gcc -o calc  -L. -lmean calc.o
calc.o: In function 'main':
calc.c:(.text+0x2f): undefined reference to 'mean'
collect2: error: ld returned 1 exit status

$ nm libmean.a
calc_mean.o:
0000000000000000 T mean

© www.minhinc.com
p17
Day 1 Morning
  1. Introduction

Shared library (also known as a shared object, or as a dynamically linked library) is similar to a archive in that it is a grouping of object files.  When a shared library is linked into a program, the final executable does not actually contain the code that is present in the shared library. Instead, the executable merely contains a reference to the shared library.

The program using the library
<<main.c>>
#include <stdio.h>
#include "calc_mean.h"
int main(){
printf ("mean of 3, 6 is %f
",mean(3,6));
return 0;
}

$ gcc -c -fPIC calc_mean.c -o calc_mean.o
$ gcc -c calc.c -o calc.o
$ gcc -shared -fPIC -o libmean.so calc_mean.o
$ ldd libmean.so

linux-vdso.so.1 =>  (0x00007fffadffe000)
libc.so.6 => /lib64/libc.so.6 (0x00007f546f7ed000)
/lib64/ld-linux-x86-64.so.2 (0x00007f546fdc4000)

$ gcc -o calc calc.o -L. -lmean
$ ldd calc

linux-vdso.so.1 =>  (0x00007fffa58de000)
libmean.so => not found
libc.so.6 => /lib64/libc.so.6 (0x00007f4e10d70000)
/lib64/ld-linux-x86-64.so.2 (0x00007f4e11146000)

$ export LD_LIBRARY_PATH=.
$ ./calc

mean of 3, 6 is 4.500000
In order to avoid LD_LIBRARY_PATH programmer can add
-Wl,rpath,<lib path> to the command link line

$ pwd
/home/sc

$ echo $LD_LIBRARY_PATH

$ rm calc
$ gcc -o calc calc.o -L. -lmean -Wl,-rpath=/home/sc/
$ ./calc
mean of 3, 6 is 4.500000

$ gcc -o calc calc.o -L. -lmean

$ ./calc
./calc: error while loading shared libraries: libmean.so: cannot open shared object file: No such file or directory

© www.minhinc.com
p18
Day 1 Morning
  1. Introduction

A calling convention describes how the arguments are passed and values returned by functions.

It also specifies how the function names are decorated.


1) C calling convention (__cdecl)
int __cdecl sumExample (int a, int b);

- Arguments are passed from right to left, and placed on the stack.
- Stack cleanup is performed by the caller.
- Function name is decorated by prefixing it with an underscore character '_' .
- The default calling convention for C and C++ programs. The advantage of this calling convention is that it allows functions with a variable number of arguments to be used. The disadvantage is that it creates larger executable.

2) Standard calling convention (__stdcall)
int __stdcall sumExample (int a, int b);

- Arguments are passed from right to left, and placed on the stack.
- Stack cleanup is performed by the called function.
- Function name is decorated by prepending an underscore character and appending a '@' character and the number of bytes of stack space required.
- It is used to call Win32 API functions. It does not allow functions to have a variable number of arguments.

3) Fast calling convention (__fastcall)
int __fastcall sumExample (int a, int b);

- The first two function arguments that require 32 bits or less are placed into registers ECX and EDX. The rest of them are pushed on the stack from right to left.
- Arguments are popped from the stack by the called function.
- Function name is decorated by by prepending a '@' character and appending a '@' and the number of bytes (decimal) of space required by the arguments.
- __fastcall attempts to put arguments in registers, rather than on the stack, thus making function calls faster.


4) Thiscall
- Arguments are passed from right to left, and placed on the stack. this is placed in ECX. Stack cleanup is performed by the called function.
- Thiscall calling convention is the default calling convention used by C++ member functions that do not use variable arguments.

© www.minhinc.com
p19
Day 1 Morning
  1. Introduction

Name mangling is changing function names to avoid name conflict. Used in function overloading.

void fun(int x) {
    cout<<x<<endl;
}
void fun(float x) {
    cout<<x<<endl;
}
int main() {
    fun(10);
    fun(10.5f);

    return 0;
}

Mangled name for funtion void fun(int x) is 
?fun@@YAXH@Z
Mangled name for funtion void fun(float x) is
?fun@@YAXM@Z
Tool - nm
#ifndef SAMPLE_H
#define SAMPLE_H
#include <iostream>
using namespace std;
struct fraction {
int numerator;
int denominator;
};
class cfraction{
int numerator;
int denominator;
public:
cfraction(int,int);
void func();
};
#endif

#include "sample.h"
cfraction::cfraction(int n,int d){
numerator=n;
denominator=d;
}
void cfraction::func(){
cout<<numerator/denominator;
}

$ g++ -c sample.cpp -o sample.o

$ nm sample.o
00000000 b .bss
00000000 d .ctors
00000000 d .data
00000000 r .eh_frame
00000000 r .rdata$zzz
00000000 t .text
0000004b t ___tcf_0
0000008a t __GLOBAL__sub_I__ZN9cfractionC2Eii
0000005d t __Z41__static_initialization_and_destruction_0ii
0000001e T __ZN9cfraction4funcEv
00000000 T __ZN9cfractionC1Eii
00000000 T __ZN9cfractionC2Eii
         U __ZNSolsEi
         U __ZNSt8ios_base4InitC1Ev
         U __ZNSt8ios_base4InitD1Ev
         U __ZSt4cout
00000000 b __ZStL8__ioinit
         U _atexit

© www.minhinc.com
p20
Day 1 Morning
  1. Introduction
© www.minhinc.com
p21
 
Day 1 Morning
  2. Functions

A calling convention describes how the arguments are passed and values returned by functions.

It also specifies how the function names are decorated.

1) C calling convention (
__cdecl
)
int __cdecl sumExample (int a, int b);

- Arguments are passed from right to left, and placed on the stack.
- Stack cleanup is performed by the caller.
- Function name is decorated by prefixing it with an underscore character '_' .
- The default calling convention for C and C++ programs. The advantage of this calling convention is that it allows functions with a variable number of arguments to be used. The disadvantage is that it creates larger executable.

2) Standard calling convention (
__stdcall
)
int __stdcall sumExample (int a, int b);

- Arguments are passed from right to left, and placed on the stack.
- Stack cleanup is performed by the called function.
- Function name is decorated by prepending an underscore character and appending a '@' character and the number of bytes of stack space required.
- It is used to call Win32 API functions. It does not allow functions to have a variable number of arguments.

3) Fast calling convention (
__fastcall
)
int __fastcall sumExample (int a, int b);

- The first two function arguments that require 32 bits or less are placed into registers ECX and EDX. The rest of them are pushed on the stack from right to left.
- Arguments are popped from the stack by the called function.
- Function name is decorated by by prepending a '@' character and appending a '@' and the number of bytes (decimal) of space required by the arguments.
- __fastcall attempts to put arguments in registers, rather than on the stack, thus making function calls faster.

4) Thiscall
- Arguments are passed from right to left, and placed on the stack. this is placed in ECX. Stack cleanup is performed by the called function.
- Thiscall calling convention is the default calling convention used by C++ member functions that do not use variable arguments.

Day 1 Morning
  2. Functions

© www.minhinc.com
p22
Name mangling is changing function names to avoid name conflict. Used in function overloading.

void fun(int x) {
    cout<<x<<endl;
}
void fun(float x) {
    cout<<x<<endl;
}
int main() {
    fun(10);
    fun(10.5f);

    return 0;
}

Mangled name for funtion void fun(int x) is 
?fun@@YAXH@Z
Mangled name for funtion void fun(float x) is
?fun@@YAXM@Z
Tool - nm
#ifndef SAMPLE_H
#define SAMPLE_H
#include <iostream>
using namespace std;
struct fraction {
int numerator;
int denominator;
};
class cfraction{
int numerator;
int denominator;
public:
cfraction(int,int);
void func();
};
#endif

#include "sample.h"
cfraction::cfraction(int n,int d){
numerator=n;
denominator=d;
}
void cfraction::func(){
cout<<numerator/denominator;
}

$ g++ -c sample.cpp -o sample.o

$ nm sample.o
00000000 b .bss
00000000 d .ctors
00000000 d .data
00000000 r .eh_frame
00000000 r .rdata$zzz
00000000 t .text
0000004b t ___tcf_0
0000008a t __GLOBAL__sub_I__ZN9cfractionC2Eii
0000005d t __Z41__static_initialization_and_destruction_0ii
0000001e T __ZN9cfraction4funcEv
00000000 T __ZN9cfractionC1Eii
00000000 T __ZN9cfractionC2Eii
         U __ZNSolsEi
         U __ZNSt8ios_base4InitC1Ev
         U __ZNSt8ios_base4InitD1Ev
         U __ZSt4cout
00000000 b __ZStL8__ioinit
         U _atexit

Day 1 Morning
  2. Functions

Function prototype provide the interface between the programmer
who defines the function and programmers who use it.

type name ( argument1, argument2, ...) statement

© www.minhinc.com
p23
- type is the type of data returned by the function.
- name is the name by which it will be possible to call the function.
- arguments (as many as wanted can be specified).
- statement is the function's body. It can be a single instruction or a
- block of instructions.
In the later case it must be delimited by curly brackets {}.

Function prototype generally placed in header files.
<<header.h>>
class A{
void func();
};

<<source.cpp>>
A::func(){
}

Day 1 Morning
  2. Functions

The stack frame, also known as activation record is the collection of all data on the stack associated with one subprogram call.
The stack frame generally includes the following components:

- The return address
- Argument variables passed on the stack
- Local variables (in HLLs)
- Saved copies of any registers modified by the subprogram that need to be restored (e.g. $s0 - $s8 in MAL).

Automatic variables are therefore represented as an offset from the stack pointer, such as 4($sp) or 8($sp).

int     function(int a, double b)
{
 int     x, y;
 ...
 return  x;
}

Possible stack frame for function:
Address Content
$sp --> F080    Saved return address
        F084    a
        F088    b
        F090    x
        F094    y
        F098    Saved register value
        F09C    Saved register value

Function can return object(value) or reference. Do not return reference or pointer to local variable, as function de-allocate stack once it returns.
Return type of overloaded function does not contribute to overloading.

© www.minhinc.com
p24
Day 1 Morning
  2. Functions

- If a function is inline, the compiler places a copy of the code of that function at each point where the function is called at compile time.
- Any change to an inline function could require all clients of the function to be recompiled.
- To inline a function, place the keyword inline before the function name and define the function before any calls are made to the function.
- The compiler can ignore the inline qualifier in case defined function is more than a line.
- An inline function does type check and it is not MACRO.

Automatic In-lining
- A function definition in a class definition is an inline function definition, even without the use of the inline specifier.
- Inline function definition must be in header files.

#include <iostream>
using namespace std;
inline void func(){ // non class function inline
cout<<"global inline func"<<endl;
}
class classA {
public:
inline const string& shorterstring(const string &s1, const string &s2); //inline
void uppercase(const string& s);
};
const string& classA::shorterstring(const string &s1, const string &s2){
return s1.size() < s2.size() ? s1:s2;
}
inline void classA::uppercase(const string& s){
s.toUpperCase();
}
int main() {
classA clsA;
cout<<clsA.shorterstring("one","three")<<endl;
func();
return 0;
}

Day 1 Morning
  2. Functions

- Virtual function can belong to a class where it supports polymorphism
- Virtual function makes entry in vtable.
class A{
int a;
virtual void f(int);
};

----------
| a:int  |
---------- vtble    ----------
| vptr   |--------->| &A::f()|
----------          ----------

struct P {
int p1;
© www.minhinc.com
p25
virtual void pvf();
};
struct S : P {
int s1;
void pvf(); // overrides P::pvf and R::pvf
void rvf(); // overrides R::rvf
void svf(); // new
};

P*, S*
  -----> --------------      --------------
         | P::vfptr  -|----->|  &S::pvf   |
         --------------      --------------
         | P::p1      |
         --------------

- static function can not be virtual as this pointer is not the implicit first argument.

Day 1 Morning
  2. Functions

- Multiple definitions for the same function name in the  same scope.  The definition of the function must differ from each other by the types and/or the number of arguments in the argument list.
- Can not overload function declarations that differ only by return type.

void print(int i) {
cout << "Printing int: " << i << endl;
}
void print(double f) {
cout << "Printing float: " << f << endl;
}
//void print(long double l) {
//cout<<"Printing long:"<<l<<endl;
//}
void print(char* c) {
cout << "Printing character: " << c << endl;
}
int main(int argc, char *argv[]) {
int i=10;
double d=20.10;
long double ld=10.10001;
char *cp="ORACLE";
print(i);
print(d);
print(ld);
print(cp);
return 0;
}

Overloading and ambiguity
- There can be ambiguity when exact matching type is not available and intermediate conversion is required where target type is more than one..
- If both functions are available that is without the overloaded argument and with overloaded argument but with default values.

In order to overcome ambiguity look the following rule is followed
a) Select candidates. Same function name.
b) Select viable function. Select function which has equal number of matching arguments.
c) Select best match function. Function that require minimum conversion.

#include <iostream>
#include <string>
using namespace std;

void print(int i){cout<<"print int"<<endl;}
void print(float f){cout<<"print float"<<endl;}
void print(char c){cout<<"print char"<<endl;}
© www.minhinc.com
p26
void print(double d){cout<<"print double"<<endl;}
void print(int *i){cout<<"print int*"<<endl;}
class complex{
public:
complex(double){}
};

class longdouble{
friend double operator+(longdouble&, int);
//friend double operator+(longdouble&, double);
public:
longdouble(int){};
operator double(){return 4.4;}
double operator+(const complex&){
cout<<"::operator+complex"<<endl;
}
};
double operator+(longdouble& l, int i){
//double operator+(longdouble& l, double i){
cout<<"global operator+"<<endl;
}
int main(){
longdouble ld(16.08);
double res=ld+15.05;
//double res=ld+15;
print(10.4);
return 0;
}

$g++ main.cpp
main.cpp: In function 'int main()':
main.cpp:38: warning: passing 'double' for argument 1 to 'longdouble::longdouble(int)'
main.cpp:39: error: ISO C++ says that these are ambiguous, even though the worst conversion
  for the first is better than the worst conversion for the second:
main.cpp:34: note: candidate 1: double operator+(longdouble&, int)
main.cpp:39: note: candidate 2: operator+(double, double) <built-in>
main.cpp:39: warning: passing 'double' for argument 2 to 'double operator+(longdouble&, int)'

Day 1 Morning
  2. Functions

- When a function is defined, a default value can be specified for each of the last parameters.
- This value will be used if the corresponding argument is left blank when calling to the function.
- This is done by using the assignment operator and assigning values for  the arguments in the function definition. If a value for that parameter  is not passed when the function is called, the default given value is used, but if a value is specified, this default value is ignored and the passed value is used instead.

#include <iostream>
using namespace std;
int sum(int a, int b=20) {
int result;
result = a + b;
return (result);
}

int sum(int a, int b){//error multiple definition
Return a+b;
}

int main () {
int a = 100;
int b = 200;
int result;
result = sum(a, b);
cout << "Total value is :" << result << endl;
result = sum(a);
cout << "Total value is :" << result << endl;
return 0;
}

© www.minhinc.com
p27
Day 1 Morning
  2. Functions

Two way parameter to function can be passed
- By value
- By reference

By value
Value is of the argument passed by callee the function is exactly copied in the caller parameter variable.

void swap(int *v1, int *v2){
int tmp=*v2;
*v2=*v1;
*v1=tmp;
}
void swapptr(int **v1, int **v2){
int *tmp=*v2;
*v2=*v1;
*v1=tmp;
}

By reference
void swap(int &v1,int &v2){
int tmp=v2;
v2=v1;
v1=tmp;
}
void swapptr( int *&v1,int *&v2){
int *tmp=v2;
v2=v1;
v1=tmp;
}

Array Value
void printvalue(int arr[10]);
void printvalue(int *arr);
void printvalue(int arr[]);

Reference
void printvalue(int (&arr)[10]);
void printvalue(int (&arr)[10][10]);

#include <iostream>
using namespace std;

void printptrtoarray(int (*arr)[4]){
int i=0,j=0;
for(i=0;i<4;i++){
for(j=0;j<4;j++)
cout<<arr[i][j]<<" ";
cout<<endl;
}
}
void printarray(int (&arr)[4][4]){
int i=0,j=0;
for (i=0;i<4;i++){
for (j=0;j<4;j++)
cout<<arr[i][j]<<" ";
cout<<endl;
}
}
void preparearray(int (&arr)[4][4]){
int i=0,j=0;
for (i=0;i<4;i++)
for (j=0;j<4;j++)
arr[i][j]=i;
}
int main(int argc,char *argv[]){
int arr[4][4];
preparearray(arr);
printarray(arr);
printptrtoarray(arr);
return 0;
© www.minhinc.com
p28
}
$ ./a.out
0 0 0 0
1 1 1 1
2 2 2 2
3 3 3 3
0 0 0 0
1 1 1 1
2 2 2 2
3 3 3 3

Day 1 Morning
  2. Functions

Unnamed function parameters are used when a particular parameter is not required but it is in design.

                       A
                 +------------+
                 | func()=0;  |
                 +------------+
                       /
                        -
                        |
    +----------------------------------+
  B |                                C |
+-------------+                 +--------------+
|   func()    |                 |    func()    |
+-------------+                 +--------------+


#include <iostream>
using namespace std;
struct A{
virtual void func(int *)=0;
};
struct B:A{
virtual void func(int *);
};
struct C:A{
virtual void func(int*);
};
void B::func(int *){
cout<<"A::func"<<endl;
}
void C::func(int *i){
cout<<"B::func"<<*i<<endl;
}
void callfunc(A* a){
int i=10;
a->func(&i);
}

int main(int argc, char *argv[]){
B b;
C c;
callfunc(&b);
callfunc(&c);
return 0;
}
$ ./a.out
A::func
B::func10

© www.minhinc.com
p29
Day 1 Morning
  2. Functions

#includexa0<stdarg.h>xa0
doublexa0average(intxa0num,...)xa0
{xa0
va_listxa0valist;xa0
doublexa0sumxa0=xa00.0;xa0
intxa0i;xa0
/*xa0initializexa0valistxa0forxa0numxa0numberxa0ofxa0argumentsxa0*/xa0
va_start(valist,xa0num);xa0



/*xa0accessxa0allxa0thexa0argumentsxa0assignedxa0toxa0valistxa0*/xa0
forxa0(ixa0=xa00;xa0ixa0<xa0num;xa0i++)xa0 {xa0
sumxa0+=xa0va_arg(valist,xa0int);xa0
}xa0
/*xa0cleanxa0memoryxa0reservedxa0forxa0valistxa0*/xa0
va_end(valist);xa0
returnxa0sum/num;xa0
}xa0

- Definexa0axa0functionxa0withxa0lastxa0parameterxa0asxa0ellipsesxa0andxa0thexa0onexa0justxa0before xa0thexa0ellipsesxa0isxa0alwaysxa0anxa0intxa0whichxa0willxa0representxa0numberxa0ofxa0arguments.xa0
- Createxa0axa0va_listxa0typexa0variablexa0inxa0thexa0functionxa0definition.xa0Thisxa0typexa0is xa0definedxa0inxa0stdarg.hxa0headerxa0file.xa0

-Usexa0intxa0parameterxa0andxa0va_startxa0macroxa0toxa0initializexa0thexa0va_listxa0variablexa0to anxa0argumentxa0list.xa0
- Thexa0macroxa0va_startxa0isxa0definedxa0inxa0stdarg.hxa0headerxa0file.xa0
- Usexa0va_argxa0macroxa0andxa0va_listxa0variablexa0toxa0accessxa0eachxa0itemxa0inxa0argumentxa0list.xa0
- Usexa0axa0macroxa0va_endxa0toxa0cleanxa0upxa0thexa0memoryxa0assignedxa0toxa0va_listxa0variable.xa0

Day 1 Morning
  2. Functions

- static keyword makes variable or function scoped.
- static keyword against global variable or global function makes it scoped to the file.
- static keyword against class variable or class function makes it scoped to the class data structure.
- static member function does not receive this pointer as first argument, it can not be virtual.
© www.minhinc.com
p30
 
Day 1 Morning
  3. Array Pointers References

- Array has to be initialized with constant variable that is qualified at compile time
int ia[get_size()]  // get_size() is function and resolved at run time
const int size=get_size(); // size resolved at run time
int ia[size]; // error
int ia[10*2-10]; // resolved at compile time

- Local copy are uninitialized where as global copy is initialized to 0.
- Array carrying objects are initialized with default constructor where ever they are declared. If default constructors are not available then array has to be initialized explicitly.
#include <iostream>
using namespace std;

const int array_size=3;
class classA{
public:
classA(){}
classA(const char* name):_name(name){}
const char* name(){return _name.c_str();}
private:
string _name;
};
int main(int argc, char *argv[]) {
classA arrayclA[array_size]={"one","two","three"};
const classA *arrayc2A=new const classA[array_size];
classA *arrayc3A=new classA[array_size]();
const int *pa=new const int[array_size];
//const int *pa=new const int[array_size]();
return 0;
}

$ g++ main.cpp
main.cpp: In function 'int main(int, char**)':
main.cpp:17: error: uninitialized const in 'new' of 'const int'

- Array can not be copied or assigned
int ia2[](ia); // error
ia2 = ia1; //error

- Array size can not be known.
sizeof(arr)/sizeof(&arr[0])

- Array memory management is in users hand. Chance of memory overwriting
const int array_size = 4;
 int main(int argc, char *argv[]) {
 int ia[] = {0, 1, 2};
 char ca[] = "C++";
 char cal[] = {'C', '+', '+', '\0' };

 /* array of objects */
 /* equivalent to "hi", "bye", "", ""*/
 string str_arr[array_size] = {"hi", "bye"};
 cout<<ia[0]<<" : "<<ia[1]<<" : "<<ia[2]<<endl;
 cout<<ca<<endl;
 cout<<cal<<endl;
 cout<<str_arr[0]<<" : "<<str_arr[1]<<" : "<<str_arr[2]<<" : "<<str_arr[3]<<endl;
 return 0;
 }

- In case of character strings use strn, i.e strncpy, strncat.

© www.minhinc.com
p31
Day 1 Morning
  3. Array Pointers References

type * pointer_name[,*pointer,name2,..];
char * terry = "hello"; //character string
const char *terry;//pointer to constant char
char *const terry;//const pointer to char
const char *const terry;//const pointer to char const

Various library function involving char pointer manipulation
str[n]cpy,str[n]cat,str[n]cmp,strdup,bcopy,memccopy,
memcpy,memmove,string,wcscpy,wcsncpy,index, rindex,
strcasecmp, strchr, strcmp, strcoll, strcspn,  strfry,
strlen,  strncasecmp,  strpbrk, strrchr, strsep, strspn,
strstr, strtok, strxfrm

Dynamically allocating array
 - allocating on heap, size of array can be estimated at run time.
 - int *pia = new int[10]; // uninitialized
            = new int [size_arrary]; // const int size_array=size_of_array();
            = new int[size_of_array()];
 - int *pia2 = new int[10](); // value initialized
 - const int *pci = new int[10]; //error, not initialized
 - const int *pci = new int[10]();// ok, initialized
 - const string *pcs = new string[10]; // empty string

Its legal to dynamically allocate empty array unless dereferenced
char arr[0]; // error
char arr = new char[0];// ok
char arr = new char[get_size()];//get_size() can return 0;

Dynamically allocated array can be deleted with delete [] pia;

Day 1 Morning
  3. Array Pointers References

- Pointer works in dynamic allocation
- Array of pointers
  classA *arrp=new classA[10];

- Pointer to array of size 10
  classA (*ptoarr)=new classA[10];
  classA arryofarry[3][10];
  ptoarr=&arryofarry[2];

int (*pa)[10]; // pointer to array of size 10
               // array of 10 ints
++pa;// incrementing will increment 10 ints
int pi[10];//array of int*

int arr[4][10]
pa=arr;
pa++

int (*pa)[10];
int arr[4][10];
pa=arr;
i=0;
for(j=0;j<4;j++){
for(k=0;k<10;k++)
arr[j][k]=i;
++i;
}
++pa;
for(j=0;j<10;j++)
cout<<pa[0][j];

© www.minhinc.com
p32
Multi dimensional array
void func(int (*a)[10]);
void func(int a[][10]);
void func(int a[4][10]);
int a[4][10];
func(a);

Day 1 Morning
  3. Array Pointers References

read from the right to left.
const char *terry;//pointer to constant char
char *const terry;//const pointer to char
const char *const terry;//const pointer to char const

Constant pointers must be initialized at the time of construction
const int *pa=new const int[10]; //error not initialized
const int *pa=new const int[10](); // value initialized

Day 1 Morning
  3. Array Pointers References

- new is used for dynamic allocation
- new operator calls operator new to allocate byte memory followed by calling default constructor to initialize the object.
- new without parentheses does not initialize built in types where as calls default constructor for class types
int *pi = new int; // uninitialized
string *ps = new string; // initialized to empty string


new when unsuccessful throws bad_alloc exception.
                           ----------------
                           |  exception   |
                           ----------------
                                   |
       +---------------------------------------------------+
       |                  |             |                  |
--------------    ---------------  -------------    -------------
|  bad_cast  |    |runtime_error|  |logic_error|    | bad_alloc |
--------------    ---------------  -------------    -------------



new[] operator can be used to allocate array of values
new[] operator calls operator new[] followed by calling default constructor.
int *pi=new int[100];

- value initialized then built in types are initialized where as class types as per the argument. When no argument is passed then default constructor is called.
- value initialized
string *ps = new string() ; // default constructor
int *pi = new int(); // pi points to an int value-initialized to 0
int *pi = new int(210); // pi points to an int value-initialized to 210

- new calls operator new to allocate the bytes of memory followed by object creation by calling default constructor.
class classA{
public:
classA(const char* name):_name(name){}
const char* name(){return _name.c_str();}
private:
string _name;
© www.minhinc.com
p33
};
int main(int argc, char *argv[]) {
classA *pc=new classA("heapallocation");
cout<<pc->name()<<endl;
return 0;
}

- delete can not be used on a pointer that is not allocated through new
- delete can happen on NULL pointers.
- After deletion pointer can still be used but its illegal and undefined.
- Dynamic allocation to const objects uses new const statement
const int *pci = new const int(1024);
delete pci;

- delete[] operator deletes the array allocated through new[]
int *pa=new int[4];
delete [] pa;

Day 1 Morning
  3. Array Pointers References

- A reference serves as an alternative name for an object.
- A reference is a compound type that is defined by preceding a variable name by the & symbol. A compound type is defined in terms of other types.
- Think of a variable name as a label attached to the variables location in the memory. Think of a reference as a second label attached to that memory location.

int ival = 1024;
int &refVal = ival;
int &refVal2; // error
int &refVal3=10; //error
int &refVal4=refVal;
int &ref[];// array of reference not valid error
int (&ref)[10];//reference to array
void printValuesRef(int (&ref)[10]);
void printValuesArr(int arr[]);
void printValuesArr1(int *arr);
void printValuesArr2(int arr[20]);
int main(int argc, char *argv[]) {
int k[10]={0,1,2,3,4,5,6,7,8,9};
printValuesRef(k);
printValuesArr(k);
printValuesArr1(k);
printValuesArr2(k);
return 0;
}
void printValuesRef(int (&ref)[10]) {
for(size_t i=0; i != 10; ++i)
cout<<ref[i]<<endl;
}
void printValuesArr(int arr[]) {
for(size_t i=0; i != 10; ++i)
cout<<arr[i]<<endl;
}
void printValuesArr1(int *arr){
for(size_t i=0; i != 10; ++i)
cout<<arr[i]<<endl;
}
void printValuesArr2(int arr[20]){
for(size_t i=0; i != 10; ++i)
cout<<arr[i]<<endl;
}

v Passing references to objects
- Reference to object is important when object is big in size and copy is costly operation. const reference is also useful when object need not be modified.
- Reference to object is mostly useful in stream objects where single object copy is maintained.

ofstream out1, out2;
ofstream print(ofstream);
out2 = print(out2); // error; cannot copy stream objects
ofstream print(ofstream&);//ok
© www.minhinc.com
p34
bool isShorter(const string &s1, const string &s2){
return s1.size() < s2.size();
}

- Its always good to have const reference as parameter.

v Returning references
- When a function returns a reference, it returns an implicit pointer to its return value. This way, a function can be used on the left side of an assignment statement.
- When returning a reference, be careful that the object being referred to does not go out of scope.
- It is not legal to return a reference to local var. But you can always return a reference on a static variable.

Day 1 Morning
  3. Array Pointers References

- Independent reference can not exist. Its only possible as class member variable then it has to be initialized in constructor.

Day 1 Morning
  3. Array Pointers References

#include <iostream>
using namespace std;

void printarray(int (&arr)[4][4]){
int i=0,j=0;
for (i=0;i<4;i++){
for (j=0;j<4;j++)
cout<<arr[i][j]<<" ";
cout<<endl;
}
}
void preparearray(int (&arr)[4][4]){
int i=0,j=0;
for (i=0;i<4;i++)
for (j=0;j<4;j++)
arr[i][j]=i;
}

int main(int argc,char *argv[]){
int arr[4][4];
preparearray(arr);
printarray(arr);
return 0;
}
$ g++ valueref.cpp
$ ./a.out
0 0 0 0
1 1 1 1
2 2 2 2
3 3 3 3
© www.minhinc.com
p35
 
Day 1 Afternoon
  4. Namespaces

-There can be chance of same name collision. Ex. library function xyz() can collide with user function xyz(). This is called namespace collision.
- Namespace provide a controlled mechanism for preventing name collision.  It provide a separate scope in which functions and variable can be defined.
- Namespaces partition the global namespace, making it easier to use independently produced libraries.

- Namespace definition
namespace namespace_one {
}

#include <iostream>
using namespace std;
class classA {
public:
const char* name() {
return "Global class A";
}
};
// first name space
namespace first_space{
void func(){
cout<<"Inside first_space" <<endl;
}
class classA {
public:
const char* name() {
return "first_space::classA";
}
};
}
// second name space
namespace second_space{
void func(){
cout << "Inside second_space" << endl;
}
class classA {
public:
const char* name() {
return "second_space::classA";
}
};
}

int main ()
{

// Calls function from first name space.
first_space::func();
classA clsA_g;
first_space::classA clsA_f;
second_space::classA clsA_s;
cout<<clsA_g.name()<<endl;
cout<<clsA_f.name()<<endl;
cout<<clsA_s.name()<<endl;
// Calls function from second name space.
second_space::func();

return 0;
}

- Namespace can be discontiguous. Writing namespace {} either defines a new namespace or adds to an existing one.
- Discontiguous namespace can be used for declaration and definition separation, where class definition, function declaration can go in namespace that is defined in a header file where as class implementation and function definition can go in cpp file.
- When class is implemented in the discontiguous namespace class name would not prepend the namespace name.
- To fetch global namespace functions :: can be used. i.e ::member_name

© www.minhinc.com
p36
- Nestested Namespace
- Namespaces can be nested where you can define one namespace inside
another name space as follows:
namespace namespace_name1 {
// code declarations
namespace namespace_name2 {
class classA{
};
}
}

- Code in the outer parts of the enclosing namespace may refer to a name in a nested namespaces only through its qualified name.
- Inner namespace variables can be used with full qualification,
i.e. namespace_name1::namespace_name2::classA;

Day 1 Afternoon
  4. Namespaces

Each namespace is a scope and members are accessed with scope resolution operator ::
To fetch global namespace functions :: can be used. i.e ::member_name

Day 1 Afternoon
  4. Namespaces

- using declaration introduces only one namespace member at a time.
map<string, vector < pair<size_t, size_t> > > word_map;
using std::map;
using std::vector;
using std::pair;
using std::string;
using std::size_t;

- using resolution operator
whole namespace can be visible in the current scope with using
namespace statement

using namespace std;
// using namespace example
#include <iostream.h>
namespace first
{
int var = 5;
}
namespace second
{
double var = 3.1416;
}
int main () {
using namespace second;
cout << var << endl;
cout << (var*2) << endl;
return 0;
}
Using both

// using namespace example
#include <iostream.h>
namespace first
{
int var = 5;
}
namespace second
{
© www.minhinc.com
p37
double var = 3.1416;
}
int main () {
{
using namespace first;
cout << var << endl;
}
{
using namespace second;
cout << var << endl;
}
return 0;
}

Day 1 Afternoon
  4. Namespaces

- An alias to long namespace name can be created. i.e namespace name = namespace_name1::namespace_name2;

Day 1 Afternoon
  4. Namespaces

- Unnamed Namesapces
- An unnamed namespace is a namespace that is defined without a name. i.e namespace {}
- Unnammed namespace can not span over files.
- Variable in global namespace can collide with unnamed namespace

int i;
namespace {
int i;
}
i=10; // error

- Since variables unnamed namespace belongs to the file it is replacement of static variable and functions which also file visibility. static is deprecated in c++ against unnamed namespace.
- If unnamed namespace is nested, then names in it are accessed in the normal way, using the enclosing namespace name(s).

namespace local {
namespace {
int i;
}
}
local::i=42; //ok

Day 1 Afternoon
  4. Namespaces

A given namespace can contain a set of overload member functions.
1. Find the set of candidate functions. A function is a candidate if a declaration for it is visible at the time of the call and it has the same name as the called function.

© www.minhinc.com
p38
2. Select the viable functions from the set of candidates. A function is viable if it has same number of parameters as the call has arguments and if each parameter could be matched by the corresponding argument.

3. Select the single best match from the viable set and generate code to call that function.
If the viable set is empty, then the call is in error, having no match
If the viable set is nonempty and there is no best match, then the call is ambiguous.

#include <iostream>
using namespace std;
int i=10;
namespace A{
void print(const char* a){
cout<<"A::print"<<a<<endl;
}
}
void print(string &str){
cout<<"::print"<<str<<endl;
}
int main(){
cout<<"i"<<::i<<endl;
using namespace A;
print("abc");
return 0;
}

$ g++ namespace.cpp
$ ./a.out
i10
A::printabc

Day 1 Afternoon
  4. Namespaces

To provide our own specializations of templates defined in a namespace,
we must ensure that the specialization definition is defined as being in
the namespace containing the original template definition.
© www.minhinc.com
p39
 
Day 2 Morning
  5. Overview of C++

A programming language that provides
 - Class
A mechanism for defining our own abstract data types. Class may have properties, methods and type members. A class defines a new type and a new scope.
- Object
An object is a region in the memory that has a type. Evaluating an expression that is an lvalue yields an object. A variable is an object that has a name.
- Encapsulation
It describes the technique of combining lower-level elements to form a new high-level identity.  Function and structures are examples of encapsulation.
- Abstraction
Separation of implementation from interface; Abstraction hides the implementation details of a type. Programmers worry about internal data structure and users worry about interfaces provided. Private data member are used for encapsulation.
- Inheritance
A derived class inherits properties from its base class. Types that are related by inheritance share a common inheritance.
- Polymorphism
Derived from a Greek word, " many forms". It is ability to obtain type specific behaviour based on the dynamic type of a reference or pointer.

Day 2 Morning
  5. Overview of C++

- Class
A mechanism for defining our own abstract data types. Class may have properties, methods and type members. A class defines a new type and a new scope. Class itself is a structure and consume 1 byte if not attributes are defined. Static members to classes belongs to class data structure.

class A{
};

- Class declaration
A class may be declared before it is defined.
class B;  // declaration
class A{ // definition
B* b;
};

- Class definition
A class body
- Abstract class
A class structure that uses encapsulation to hide its implementation, allowing programmers using the type to think abstractly about what the type does rather than concretely about how the type is represented.

- Concrete class
© www.minhinc.com
p40
A class that exposes its implementation. i.e std::pair. All attributes are public

Day 2 Morning
  5. Overview of C++

- Attributes are non function member fields in class. It can built in types or user defined types. It can volatile, const, static const,  reference, const reference, pointer or const pointer types.
- Methods are function member variable., Methods does not contribute in size of the class and they get first parameter as pointer to object of the class also called this pointer. Methods can be static, virtual or const. Static methods belongs to class data structure where as non  static belongs to object., const member function does not allow attributes to be changed.

Day 2 Morning
  5. Overview of C++



- Private members accessible to friends and other class members. Private members are used as implementation library. If a class is derived private or protected it is implementation based inheritance.
- Protected members are accessible to friends, other class members and derived class classes. It different from protected in order that derive class (public or protected inheritance) can also use it. It comes under implementation based inheritance.
- Public members are accessible to everyone. It is mostly used as interface to the user of class. public inheritance is also a interface base inheritance.

Day 2 Morning
  5. Overview of C++

- Constructor is a member function with name same as class name with no return type. It has special privilege as it is called implicitly an class is instantiated. Constructor can have arguments. when no argument is specified constructor is called default constructor. Explicit default constructor does not implicit type conversion.
- Copy Constructor takes const reference to same class type as an argument to the function. It is used to copy one object to other of same type.
© www.minhinc.com
p41
- Synthesized constructor are constructors generated through compiler when it is not provided by the programmer. If no constructor is provided then default constructor, copy constructor, assignment operator and destructor is provided through the compiler. If any of the constructor is provided then default constructor is not provided through the compiler though other copy control can be synthesized if not available.
- Parametrized Constructor
A constructor can have parameters. This helps to assign initial value to an object at the time of its creation.

#include <iostream>
using namespace std;
class Line{
public:
double length( void );
Line(double);   // This is the constructor declaration
~Line();  // This is the destructor: declaration
private:
double _length;
};
// Member functions definitions including constructor
Line::Line(double length) {
cout << "Object is being created" << endl;
_length=length;
}
Line::~Line(void){
cout << "Object is being deleted" << endl;
}
double Line::length( void ){
return _length;
}
// Main function for the program
int main( ){
Line line(10);
cout << "Length of line : " << line.length() <<endl;
return 0;
}

Day 2 Morning
  5. Overview of C++

- Copy Constructor,Assignment operator and destructor are copy control.
- Copy constructor is used  at following places
>The constructor that takes single parameter (const reference) as argument to class type itself.
>Explicitly or implicitly initialize one object from another of the same type.
string securityId="99999-99999-99999";
string securityId2=securityId;
string securityId2(securityId);

>Copy an object to pass it as an argument to a function.
string secuirtyId="123-123-123";
void func(const string secid);
func(secuirtyid);

>Copy an object to return it from a function.
string make_plural(size_t s, const string& str, const string& end) {
return (size == 1?str:str+end);
}

>Initialize the elements in a sequential container.
  vector<string> stringvec(5);

This creates five temporary string object with default constructor and then  creates five vector strings  calling its copy constructor on five temporary objects.
>Initialize elements in an array from a list of element initializers
string stringarry[] = { "one", "two", "three"}
#include <iostream>
using namespace std;
© www.minhinc.com
p42
void func(string str) {
cout<<"string : "<<str<<endl;
}
class classA {
public:
classA() {
cout<<"default constructor"<<endl;
}
classA(const classA& cls) {
cout<<"copy constructor"<<endl;
}
explicit classA(const string& str) {
cout<<"overloaded constructor : "<<str<<endl;
}
classA(const char *cp) {
cout<<"overload const char constructor :"<<cp<<endl;
}
classA& operator=(const string& str) {
cout<<"assignment operator "<<str<<endl;
return *this;
}
};
int main(int argc, char *argv[]) {
classA clsarr[] = { classA(string("one")),
    classA(string("two")),
    classA(string("three"))
};
func(string());
return 0;
}

- More on copy constructor
>Copy constructor should be declared private if copy need to be disabled, i.e. ostream.
>private copy constructor may need to declared but not defined if copy needs to be disabled from friends and member functions.

>Default behaviour of synthesized copy constructor is to do member wise copy. Shallow copy.
- Synthesized Copy Constructor
>When copy constructor is synthesized through compiler.
>Unlike default constructor it is synthesized even though other constructors we define.

- Parametrized constructor
- Other overloaded constructor can be declared as per the need.

- Assignment operator can be overloaded to define what it means to assign one object of a class type to another of the same type. The assignment operator must be a member of its class and should return a reference to its object. The compiler synthesizes the assignment operator if the class does not explicitly define one.
- Assignment operator can be of non class type.
- Assignment operator can be compound type.
#include <iostream>
using namespace std;
class classA {
public:
classA(){
_data="";
}
classA(const classA& c) {
cout<<"copy constructor"<<endl;
}
classA& operator=(const char* cp) {
cout<<"char pointer"<<endl;
_data+=cp;
return *this;
}
classA& operator=(const string& cs) {
cout<<"constant string"<<endl;
_data+=cs;
return *this;
}
classA& operator=(char c) {
cout<<"char"<<endl;
_data+=c;
return *this;
}
classA& operator+=(const classA& rhs) {
_data+=rhs._data;
return *this;
}
© www.minhinc.com
p43
string& data() {
return _data;
}
private:
string _data;
};

int main() {
classA cls;
cls = "one";
cls = string(":two");
cls=':';
classA rhs;
rhs="three";
cls+=rhs;
cout<<"cls data : "<<cls.data()<<endl;
return 0;
}

- Destructor
A destructor is a special member function of a class that is executed whenever an object of it's class goes out of scope or whenever the delete expression is applied to a pointer to the object of that class.

- A destructor will have exact same name as the class prefixed with a tilde (~) and it can neither return a value nor can it take any parameters.
- Destructor can be very useful for releasing resources before coming out of the program like closing files, releasing memories etc.

#include <iostream>
using namespace std;
class Line{
public:
double length( void );
Line();   // This is the constructor declaration
~Line();  // This is the destructor: declaration
private:
double _length;
};
// Member functions definitions including constructor
Line::Line(void){
cout << "Object is being created" << endl;
_length=0;
}
Line::~Line(void){
cout << "Object is being deleted" << endl;
}
double Line::length( void ){
return _length;
}
// Main function for the program
int main( ){
Line line;
cout << "Length of line : " << line.length() <<endl;
return 0;
}

Day 2 Morning
  5. Overview of C++

- An object is region in memory that has a type. A value is object that has a name.
int i(0);
struct A a;
struct A a[4]={1,2,3,4};

© www.minhinc.com
p44
Day 2 Morning
  5. Overview of C++

- Define and initialize static array
- Array has to be initialized with constant variable that is qualified at compile time
int ia[get_size()]// get_size() is function and resolved at run time
const int size=get_size(); // size resolved at run time
int ia[size]; // error
int ia[10*2-10]; // resolved at compile time

- Local copy are uninitialized where as global copy is initialized to 0.
- Array carrying objects are initialized with default constructor where ever they are declared.
If default constructors are not available then array has to be initialized explicitly
const int array_size=3;
class classA{
public:
classA(const char* name):_name(name){}
const char* name(){return _name.c_str();}
private:
string _name;
};

int main(int argc, char *argv[]) {
classA arrayclA[array_size]={"one","two","three"};
cout<<arrayclA[0].name()<<" : "<<arrayclA[1].name()<<" : "<<arrayclA[2].name()<<endl;
return 0;
}

- Array can not be copied or assigned
int ia2[](ia); // error
ia2 = ia1; //error

- Array size can not be known.
- sizeof(arr)/sizeof(&arr[0])
- Array memory management is in users hand. Chance of memory overriding
- const int array_size = 4;
int main(int argc, char *argv[]) {
int ia[] = {0, 1, 2};
char ca[] = "C++";
char cal[] = {'C', '+', '+', '\0' };

/* array  of objects */
/* equivalent to "hi", "bye", "", ""*/
string str_arr[array_size] = {"hi", "bye"};
cout<<ia[0]<<" : "<<ia[1]<<" : "<<ia[2]<<endl;
cout<<ca<<endl;
cout<<cal<<endl;
cout<<str_arr[0]<<" : "<<str_arr[1]<<" : "<<str_arr[2]<<" : "<<str_arr[3]<<endl;
return 0;
}

- In case of character strings use strn, i.e strncpy, strncat.


- Dynamic Allocating arrays
allocating on heap, size of array can be estimated at run time.
int *pia = new int[10]; // uninitialized
         = new int [size_arrary]; // const int size_array=size_of_array();
         = new int[size_of_array()];
int *pia2 = new int[10](); // value initialized
const int *pci = new int[10]; //error, not initialized
const int *pci = new int[10]();// ok, initialized
const string *pcs = new string[10]; // empty string

Its legal to dynamically allocate empty array unless dereferenced
char arr[0]; // error
© www.minhinc.com
p45
char arr = new char[0];// ok
char arr = new char[get_size()];//get_size() can return 0;

- Dynamically allocated array can be deleted with delete [] pia;

Day 2 Morning
  5. Overview of C++

- Virtual function can belong to a class where it supports polymorphism
- Virtual function makes entry in vtable.
- Virtual function do not support function overloading in polymorphism.
- When data abstraction is required then virtual function is declared as pure virtual.
- Data abstraction refers to, providing only essential information to the outside world and hiding their background details,  i.e., to represent the needed information in program without presenting the details.
- Data abstraction is a programming (and design) technique that relies on the separation of interface and implementation.
- Data abstraction layer also known as interfaces must not contain any attributes and only operations should be supported either pure virtual or default implementation implemented.

class ITelevision {
public:
virtual void switchto(bool onoff=0) = 0;
virtual void volume(int level) = 0;
virtual void channel(int number) = 0;
};
class modeltelevision: public ITelevision {
public:
virtual void switchto(bool onoff) {
cout<<"Tv is switched "<<(onoff?" ON ": " OFF ")<<endl;
}
virtual void volume(int level) {
cout<<"Volume raised to : "<<level<<endl;
}
virtual void channel(int number) {
cout<<"channel number : "<<number<<endl;
}
};
int main(int argc, char *argv[]) {
ITelevision *tv=new modeltelevision;
tv->switchto(true);
tv->channel(5);
tv->volume(8);
tv->switchto(false);
return 0;
}

Day 2 Morning
  5. Overview of C++

- A mutable data member that in never a const can be modified even in
const member function. A const member function can not modify attribute.
class widget:QWidget{
mutable int sizehintcont;
QSize sizeHint() const;
};
© www.minhinc.com
p46
QSize widget::sizeHint()const{
++sizehintcount;
return QSize(10,10);
}

Day 2 Morning
  5. Overview of C++

- Classes can be interrelated by means of inheritance and containment.
If a class derives other then it is inheritance. Class carries all parent attributes and methods. Parent attributes and methods can be called in Derived class context. Base class object comes inside of derive class object. Template method.

struct A:B{
};
A *, B* --> +-------------+
            |   B::b:int  |
            ---------------
            |   A::a:int  |
            +-------------+

- A class can keep other class as attributes known as containment. Here
container class can keep or throw the contained class as per need.
- Container is important in strategy pattern.

Day 2 Morning
  5. Overview of C++

- Data or function member that is not a part of any object but is shared by all objects of a given class. Static is part class structure.

- Static methods can not call member variables not static as they are part of object structure.
- Static methods does not contain this pointer.
- No polymorphism on static methods. It can not be virtual.
- We can define class members static using static keyword. When we declare a member of a class as static it means no matter how many objects of the class are created, there is only one copy of the static
member.
- A static member is shared by all objects of the class. All static data is initialized to zero when the first object is created, if no other initialization is present.

- By declaring a function member as static, you make it independent of any particular object of the class. A static member function can be called even if no objects of the class exist.
- A static member function can only access static data member, other static member functions and any other functions from outside the class.
- Static member functions have a class scope and they do not have access to the this pointer of the class.

#include <iostream>
© www.minhinc.com
p47
using namespace std;
class Box{
public:
static int objectCount;
Box(double l=2.0, double b=2.0, double h=2.0){
cout <<"Constructor called." << endl;
length = l;
breadth = b;
height = h;
objectCount++;
}
double Volume(){
return length * breadth * height;
}
static int getCount(){
return objectCount;
}
private:
double length;     // Length of a box
double breadth;    // Breadth of a box
double height;     // Height of a box
};
int Box::objectCount = 0;
int main(void){
cout << "Inital Stage Count: " << Box::getCount() << endl;
Box Box1(3.3, 1.2, 1.5);    // Declare box1
Box Box2(8.5, 6.0, 2.0);    // Declare box2
cout << "Final Stage Count: " << Box::getCount() << endl;
return 0;
}

Day 2 Morning
  5. Overview of C++

- A friend function of a class is defined outside that class scope but it has the right to access all private and protected members of the class.
- Even though the prototypes for friend functions appear in the class definition, friends are not member functions.
- A friend can be a function, function template, or member function, or a class or class template, in which case the entire class and all of its members are friends.
- To declare a function as a friend of a class, precede the function Prototype in the class definition with keyword friend as follows:

#include <iostream>
using namespace std;
class Box {
double width;
public:
friend void printWidth( Box box );
void setWidth( double wid );
};
void Box::setWidth( double wid ) {
width = wid;
}
void printWidth( Box box ) {
cout << "Width of box : " << box.width <<endl;
}

int main( ) {
Box box;
box.setWidth(10.0);
printWidth( box );
return 0;
}

- Friend class similar to friend function gets access to friends all
attributes and methods. A friend class though have no special access
to base or derived class of the class to which it friend with.

class A{
protected int a;
};
© www.minhinc.com
p48
class B:publlic A{
private int b;
friend class D;
};
class D{
public:
void print(A apar){
cout<<apar.b;
}
};
© www.minhinc.com
p49
 
Day 2 Morning
  6. Virtual concepts

- Unexpected object slicing can happen in which assignment by value
is not polymorphic.

struct A
{
A(int a) : a_var(a) {}
int a_var;
};
struct B : public A
{
B(int a, int b) : A(a), b_var(b) {}
int b_var;
};
B &getB()
{
static B b(1, 2);
return b;
}
int main()
{
// Normal assignment by value to a
A a(3);
a = getB();
// a.a_var == 1, b.b_var not copied to a
B b2(3, 4);
A &a2 = b2;
// Partial assignment by value through reference to b2
a2 = getB();
// b2.a_var == 1, b2.b_var == 4!
return 0;
}

Day 2 Morning
  6. Virtual concepts

- A constructor can not resolve virtual functions and function would
resolved at compile time.
class A{
public:
A(){
func();
}
virtual void func(){
cout<<"A::func"<<endl;
}
};
class B:public A{
public:
void func(){
cout<<"B::func"<<endl;
}
};

© www.minhinc.com
p50
int main(int argc, char *argv[]){
A* b=new B;
return 0;
}

Day 2 Morning
  6. Virtual concepts

- Calling virtual function from non virtual function supports
polymorphism. Template method.

Day 2 Morning
  6. Virtual concepts

- No non member virtual function can exist as vptr does not exist in file
context.

Day 2 Morning
  6. Virtual concepts

- In dual dispatching a function dispatches the request to other concrete
function depending on the run time types of two objects involved in the call.

struct Figure {
 void printOn( Printer *printer );
}
struct Printer {
 void printCircle( Circle *circle );
 void printRectangle( Rectangle *rectangle );
}

Next, we write our two printers:

struct InkjetPrinter :Printer {
 void printCircle( Circle *circle ) {
 cout<<"Inkjet printer prints a cirlce.";
 }
 void printRectangle( Rectangle *rectangle ) {
 cout<<"Inkjet printer prints a rectangle.";
 }
}
struct PostscriptPrinter : Printer {
 void printCircle( Circle *circle ) {
 cout<<"PostScript printer prints a cirlce.";
 }
 void printRectangle( Rectangle *rectangle ) {
 cout<<"PostScript printer prints a rectangle.";
 }
}

struct Circle :Figure {
 void printOn( Printer *printer ) {
© www.minhinc.com
p51
 printer->printCircle( this );
 }
}
struct Rectangle : Figure {
 void printOn( Printer *printer ) {
  printer->printRectangle( this );
}
}

int main (int argc, char *argv[]){
const int FIGURECOUNT=2;
const int PRINTERCOUNT=2;
Figure *figures[]{ new Circle, new Rectangle };
Printer *printers[] { new PostscriptPrinter, new InkjetPrinter };
for(int i=0;i<FIGURECOUNT;++i){
 for(int j=0;j<PRINTERCOUNT;++j){
  figures[i]->printOn(printers[j]);
 }
}
return 0;
}
© www.minhinc.com
p52
 
Day 2 Afternoon
  7. Copy Control

- Default Constructor
 - Constructor having no parameter is default constructor. Default in the sense if object is constructed with any argument passed then this constructed gets called.
 - A synthesized default constructor is provided by the compiler in case there is no other constructor available for the class.

 - Default constructor can be overloaded in fashion that other functions are overloaded in c++. It can have default parameter values also. Overloaded functions comes under two categories

- Copy Constructor
- Parametrized constructor

- Copy Constructor
- Copy constructor falls in a category called Copy Control. Copy constructor is used at following places
- The constructor that takes single parameter (const reference) as argument to class type itself.

- Explicity or implicitly initialize one object from another of the same type.
string securityId="99999-99999-99999";
string securityId2=securityId;
string securityId2(securityId);

- Copy an object to pass it as an argument to a function.
string secuirtyId="123-123-123";
void func(const string secid);
func(secuirtyid);

- Copy an object to return it from a function.
string make_plural(size_t s, const string& str, const string& end) {
return (size == 1?str:str+end);
}

- Initialize the elements in a sequential container.
vector<string> stringvec(5);

This creates five temporary string object with default constructor and then creates five vector strings calling its copy constructor on five temporary objects.
- Initialize elements in an array from a list of element initializers
string stringarry[] = { "one", "two", "three"}

#include <iostream>
using namespace std;
void func(string str) {
cout<<"string : "<<str<<endl;
}
class classA {
public:
classA() {
cout<<"default constructor"<<endl;
}
classA(const classA& cls) {
cout<<"copy constructor"<<endl;
}
explicit classA(const string& str) {
cout<<"overloaded constructor : "<<str<<endl;
}
classA(const char *cp) {
cout<<"overload const char constructor :"<<cp<<endl;
}
classA& operator=(const string& str) {
cout<<"assignment operator "<<str<<endl;
return *this;
}
};
int main(int argc, char *argv[]) {
classA clsarr[] = { classA(string("one")),
© www.minhinc.com
p53
                    classA(string("two")),
                    classA(string("three"))
                  };
func(string());
return 0;
}

v Creating and using a copy constructor
- The copy constructor is a constructor which creates an object by initializing it with an object of the same class, which has been created previously. The copy constructor is used to:
- Initialize one object from another of the same type.
- Copy an object to pass it as an argument to a function.
- Copy an object to return it from a function.
- If a copy constructor is not defined in a class, the compiler itself defines one, irrespective of other constructor defined by user and makes shallow copy.

classname (const classname &obj) {
   // body of constructor
}

Here, obj is a reference to an object that is being used to initialize another object.

Day 2 Afternoon
  7. Copy Control

When copy constructor is synthesized through compiler.
Unlike default constructor it is synthesized even though other constructors we define.
- More on copy constructor
Copy constructor should be declared private if copy need to be disabled,
i.e. ostream.
private copy constructor may need to declared but not defined if copy needs to be disabled from friends and member functions
Default behaviour of synthesized copy constructor is to do member wise copy. Shallow copy.

Day 2 Afternoon
  7. Copy Control

- constructor's implicit conversion can be prevented by declaring the constructor explicit.
class A{
public:
explicit A(const std::string &str="");
};
string lstr="abc-def";
void func(A a){
}
func("abc-def");//wrong
func(A(lstr));

© www.minhinc.com
p54
Day 2 Afternoon
  7. Copy Control

- declaration copy constructor and equal operator private
- do not define
- example ostream

Day 2 Afternoon
  7. Copy Control

Assignment operator can be member or non member functions.  for member function first member of the function is bound to 'this' pointer.
struct A{
A& operator=(const A&);
}
void operator=(const A&,const A&);
- synthesized assignment operator
if assignment operator is not available compiler pushes a synthesized.
- does member wise copy (shallow for pointer)
- does array member index wise copy
A a;
A b=a; // copy constructor


#include <iostream>
using namespace std;
class classA {
public:
classA(){
_data="";
}
classA(const classA& c) {
cout<<"copy constructor"<<endl;
}
classA& operator=(const char* cp) {
cout<<"char pointer"<<endl;
_data+=cp;
return *this;
}
classA& operator=(const string& cs) {
cout<<"constant string"<<endl;
_data+=cs;
return *this;
}

classA& operator=(char c) {
cout<<"char"<<endl;
_data+=c;
return *this;
}
classA& operator+=(const classA& rhs) {
_data+=rhs._data;
return *this;
}
string& data() {
return _data;
}
private:
string _data;
};
int main() {
classA cls;
cls = "one";
cls = string(":two");
cls=':';
classA rhs;
rhs="three";
cls+=rhs;
cout<<"cls data : "<<cls.data()<<endl;
return 0;
}

© www.minhinc.com
p55

 
Day 2 Afternoon
  7. Copy Control

Destructor is automatically called when an object is released from the memory, either because its scope of existence has finished (for example, if it was defined as a local object within a function and the function ends) or because it is an object dynamically assigned and it is released using operator delete.

The destructor must have the same name as the class with a tilde (~) as prefix and it must return no value.
- destructor is synthesised by compiler if not declared
- destructor can be virtual to support polymorphism and get derived class
  destructor called with delete on base class pointer.
- destructor can be called as method.

// example on constructors and destructors
#include <iostream.h>
class CRectangle {
int *width, *height;
public:
CRectangle (int,int);
~CRectangle ();
int area (void) {return (*width * *height);}
};
CRectangle::CRectangle (int a, int b) {
width = new int;
height = new int;
*width = a;
*height = b;
}
CRectangle::~CRectangle () {
delete width;
delete height;
}
int main () {
CRectangle rect (3,4), rectb (5,6);
cout << "rect area: " << rect.area() << endl;
cout << "rectb area: " << rectb.area() << endl;
return 0;
}
© www.minhinc.com
p56
 
Day 3 Morning
  8. Object Model and Polymorphism

- In order to maintain uniform representation of objects for all classes table driven object model places attributes and methods to two different tables.
The class object contains the pointers to the two member tables. The member function table is a sequence of slots, with each slot addressing a member. The data member table directly holds the data.

                                     attribute
                         |--------> -----------------
                         |          |         x |
                         |          --------------
                         |          |         y |
                         |          ---------------
        -------------    |
        |           |    |
        |       o---------
        -------------
        |           |
        |       o---------
        -------------    |
          Point pt;      |            method
                         |-------> --------------
                                   |         o--|---->
                                   --------------
                                   |         o--|---->
                                   --------------
                                   |         o--|---->
                                   --------------

Day 3 Morning
  8. Object Model and Polymorphism

- class A{
int a;
void f(int);
void g(int);
void h(int);
};

class B:A{
int b;
void g();
};

class C:B{
int c:
void h();
};

class C:
-------- A*
| a:int|
--------

-------- A*,B*
| a:int|
| b:int|
---------

C* pc=new C;
B* b=(B*)pc;

--------- <-- A*,B*,C*
| a:int |
| b:int |
| c:int |
---------

© www.minhinc.com
p57
$ cat main.cpp
#include <iostream>
using namespace std;
struct A{
int a;
void f();
void g();
void h();
};
struct B:A{
int b;
void g();
};
struct C:B{
int c;
void h();
};
int main(){
C* c=new C;
cout<<"C* "<<c<<endl;
cout<<"B* "<<dynamic_cast<B*>(c)<<endl;
cout<<"A* "<<dynamic_cast<A*>(c)<<endl;
cout<<"int a "<<&c->a<<endl;
cout<<"int b "<<&c->b<<endl;
cout<<"int c "<<&c->c<<endl;
return 0;
}

----------- <----A*,B*,C* (0xc661010)
| a:int   | (0xc661010)
-----------
| b:int   | (0xc661014)
-----------
| c:int   | (0xc661018)
-----------

$ ./a.out
C* 0xc661010
B* 0xc661010
A* 0xc661010
int a 0xc661010
int b 0xc661014
int c 0xc661018

Day 3 Morning
  8. Object Model and Polymorphism

- class A{
int a;
void f(int);
void g(int);
void h(int);
};

class B{
int b;
void g();
};

class C:A,B
{
int c;
void h();
};

--------- <---A*,C*
| a:int |
--------- <--- B*
| b:int |
---------
| c:int |
---------

$ cat main.cpp
#include <iostream>
using namespace std;

struct A{
© www.minhinc.com
p58
int a;
void f();
void g();
void h();
};

struct B{
int b;
void g();
};

struct C:A,B{
int c;
void h();
};

int main(){
C* c=new C;
cout<<"C* "<<c<<endl;
cout<<"B* "<<dynamic_cast<B*>(c)<<endl;
cout<<"A* "<<dynamic_cast<A*>(c)<<endl;
cout<<"int a "<<&c->a<<endl;
cout<<"int b "<<&c->b<<endl;
cout<<"int c "<<&c->c<<endl;
return 0;
}
$ ./a.out
C* 0x176fe010
B* 0x176fe014
A* 0x176fe010
int a 0x176fe010
int b 0x176fe014
int c 0x176fe018

----------- <----A*,C* (0x176fe010)
| a:int   | (0x176fe010)
----------- <----B*(0x176fe014)
| b:int   | (0x176fe014)
-----------
| c:int   | (0x176fe018)
-----------

Day 3 Morning
  8. Object Model and Polymorphism

- virtual methods are arranged in a separate table(vtable).
- Object layout carries a vptr to the vtable.
- vptr are first field in object layout

class A{
virtual func();
int a;
};

Object layout           vtble
-------------         ---------------
|  vptr     | ------->|  &A::func() |
-------------         ---------------
|  a:int    |
-------------

Day 3 Morning
  8. Object Model and Polymorphism

- SI
vtable of base class gets merged to derived class vtable.

- MI
© www.minhinc.com
p59
vtable of secondary base class are different than derived or primary base class.
Base class functions are called with base class this pointer not the actual object pointer

class A{
int a;
virtual void f(int);
virtual void g(int);
virtual void h(int);
};
class B:A{
int b;
void g();
};
class C:B{
int c:
void h();
};


--------- <---A*,B*,C*
| a:int | vtble  ------------
| vptr  |--------|  A:f(int)|
---------        |  B:g(int)|
| b:int |        |  C:h(int)|
---------        ------------
| c:int |
---------

C *pc;
pc->g(2);
(*(pc->vptr[1]))(pc,2);
class C:A,B{int c:void h();};

--------- <-- A*,C*----------
| a:int | --------| A::f(int);
| vptr  |         | C::h(int);
--------- <-- B*  ------------
| b:int |
---------
| c:int |
---------

C* pc;
B* pb;
pb = (B*)pc; // pb = (B*)((char*)pc+delta(B))
pb = pc; // pb = (B*)((char*)pc+delta(B))
pc = pb; // error: cast needed
pc = (C*)pb; // pc = (C*)((char*)pb-delta(B))


-delta storage.
class A{virtual void f();};
class B{virtual void f(); virtual void g();};
class C:A , B{void f();};
A* pa=new C;
B* pb=new C;
C* pc=new C;
pa->f();
pb->f();
pc->f();

In order to fix this pointer when calling the base class function in context of derived class object detla mechanism is used.

In order to shift top to pb* place delta(B) is calculated at compile time.

In order to have it at run time it is stored in vtable where function entry is a structure itself with first field is a function pointer and second field as delta(B).

struct vtbl_entry{
void  (*fct)();
int delta;
};

-------------  vtbl    -------------
|  vtpr     | -------> | &C::f()| 0 |
| A part    |          -------------
-------------
|           | vtbl    ----------------------
| vptr      | ------> | &C::f()| - delta(B)|
| B part    |         ----------------------
-------------         | &B::g()| 0 |
|           |         --------------
| C part    |
-------------
© www.minhinc.com
p60

B* pb=new C;
pb->f();
// register vtbl_entry* vt=&pb->vtbl[index(f)];
// (*vt->fct)((B*)((char*)pb+vt->delta))
                    ^
                    |
                    +--------- New this pointer

Day 3 Morning
  8. Object Model and Polymorphism

- virtual base
class W {
 virtual void f();
 virtual void g();
 virtual void h();
 virtual void k();
};
class AW:virtual W{ void g();...};
class BW:virtual W{ void f();...};
class CW:AW, BW { void h();....};
CW* pcw=new CW;
pcw->f();  //BW::f()
pcw->g();  /AW::g()
pcw->h();  //CW::h()
((AW*)pcw)->f();   /BW::f();


          -----------------
......... |
.         | AW part |
v         |         |
.         -----------------
......... |
.         | BW part |
v         |         |
.         -----------------
.         |         |
.         | CW part |
v         |         |        vtbl:
.         ----------------- ------------------------------
...>      | vptr ..........>| BW::f | delta(BW)-delta(W) |
          |         |       | AW::g | -delta(W) |
          | W part  |       | CW::h | -delta(W) |
          |         |       | W::k  | 0         |
          ----------------- ------------------------------



....> W { f g h k } <...
|          |

|          |
AW { g }          BW { f }
|          |

|          |
...<... CW { h } ...>...

Note that a call ''up'' through one path of the DAG to a virtual function may result in the call of a function (re-defined) in another path (as happened in the call ((AW*)pcw)->f() in the example above).

Day 3 Morning
  8. Object Model and Polymorphism

© www.minhinc.com
p61
-Thunk based object model, vtable entry is not two field structures instead it is has function pointer to virtual function. vtable of base class contains thunk entries for functions which is overridden by derived class. Aduster thunk actually adjust the this pointer first then call the function in unsimilar to offset based approach where base class function entry from the vtable was called with adjusted this pointer.

Day 3 Morning
  8. Object Model and Polymorphism

struct P {
int p1;
virtual void pvf();
};
struct R {
int r1;
virtual void pvf(); // new
virtual void rvf(); // new
};
struct S : P, R {
int s1;
void pvf(); // overrides P::pvf and R::pvf
void rvf(); // overrides R::rvf
void svf(); // new
};


R*
----->  --------------      --------------
        | R::vfptr   |----->| &R::pvf    |
        --------------      --------------
        | R::r1      |      | &R::rvf    |
        --------------      --------------


P*, S*
-----> --------------      --------------
       | P::vfptr  -|----->|  &S::pvf   |
       --------------      --------------
       | P::p1      |
       --------------      --------------
R*---> | R::vfptr   |----> | &thunk1    |
       --------------      --------------
       | R::r1      |      | &S::rvf    |
       --------------      --------------
       | S::s1      |
       --------------

       thunk1: this == SdPR; goto S::pvf
© www.minhinc.com
p62
 
Day 3 Morning
  9. Inheritance

- Base class
Class from which another class inherits. The members of the base class become members of the derived class.


- Derived class
A class inherits from another class. Member of the base class are also members of the derived class. Parent attributes and methods can be called in Derived class context. Base class object comes inside of derive class
object.

struct A:B{
};
A *, B* --> +-------------+
            |   B::b:int  |
            ---------------
            |   A::a:int  |
            +-------------+

A derived class can redefine the members of its base (function overriding) and can define new members. A derived-class scope is nested in the scope of its base class, so the derived class can access members of the base class
directly.

- Inheritance allows us to define a class in terms of another class, which makes it easier to create and maintain an application.
- This also provides an opportunity to reuse the code functionality and fast implementation time.
- When creating a class, instead of writing completely new data members and member functions, the programmer can designate that the new class should inherit the members of an existing class. This existing class is called the base class, and the new class is referred to as the derived class.
- The idea of inheritance implements the is a relationship. For example,
mammal IS-A animal, dog IS-A mammal hence dog IS-A animal.

- A class can be derived from more than one classes, which means it can inherit data and functions from multiple base classes.  class derived-class: access-specifier base-class

Access                public  protected  private
Same class            yes     yes        yes
Derived classes       yes     yes        no
Outside classes       yes     no         no

- A derived class inherits all base class methods with following exceptions:
Constructors, destructors and copy constructors of the base class.
Overloaded operators of the base class.
The friend functions of the base class.

© www.minhinc.com
p63
Day 3 Morning
  9. Inheritance

- A member function that defines type-specific behaviour. Calls to a virtual made through a reference or pointer are resolved at run time, based on the type of the object to which the reference or pointer is bound.

Day 3 Morning
  9. Inheritance

- A virtual function declared in the class header using =0 at the end of the function's parameter list.  A pure virtual is one that need not be (but may be) defined by the class. A class with a pure virtual is an abstract class. If a derived class does not define its own version of an inherited pure virtual, then the derived class is abstract as well.

Day 3 Morning
  9. Inheritance

public      protected   private (inheritance type)

public     public      protected   private
protected  protected   protected   private
private    private     private     private
  ^
  |
  |
  +----dbase class access control

Day 3 Morning
  9. Inheritance

- Inheritance in which a class has more than one immediate base class.
The derived class inherits the members of all its base classes. Multiple base classes are defined by naming more than one base class in the class derivation list. A separate access label is required for each base class.

- Multiple inheritance is useful when an entity carries multiple identity.
Multiple type of task can be performed on the same object.  A multi homed computer can be a router or a server.
© www.minhinc.com
p64

-----------                 ------------
|  server |                 | router   |
-----------                 ------------
    /\                          / \
     -                            -
     |                            |
     +----------------------------+
                    |
             --------------
             | machine    |
             --------------

class A{}
class B{}
class C:A,B{};
---------- <-- A*, C*
| A Part |
---------- <-- B*
| B Part |
----------
| C Part |
----------

C* pc;
pc->bg(2);//bg is class B function
bg_F1B((B*)((char*)pc+delta(B)),2);

Day 3 Morning
  9. Inheritance

- Polymorphism means "many forms". It refers to obtain type specific behaviour based on the dynamic type of a reference or pointer.

In inheritance base class shows polymorphic behaviour. Base class pointer accept down the line derived class concrete objects.

                                          f()
                                       <|---- B
                            A  <|----- |      <|------ D
                            f()        <|---- C        f(),g()
                                          g()

void func(A* pa){  <--- A* is polymorphic and accepts object of derived class B,C,D
pa->f();// always bound to base A::f(). A::f() is not polymorphic
func(new B);
func(new C);
func(new D);

When a function in base class is virtual then function becomes polymorphic
                                      virtual f()
                                       <|---- B
                            A  <|----- |      <|------ D
                    virtual f()        <|---- C        f(),g()
                                      Virtual g()

void func(A* pa){
ps->f();// polymorphic
}
func(new B);//pa->f() calls B::f()
func(new D);// pa->f() calls D::f()

© www.minhinc.com
p65
Day 3 Morning
  9. Inheritance

- Friend function and friend class does not follow inheritance rule and class A friend to class B will not be friend to class C that is either parent or derived from class B.

Day 3 Morning
  9. Inheritance

- If base class function(non virtual) is also defined in device class, derive class function override the base class function.

- No polymorphism in case of overriding. Base class function call through base class pointer always resolves to base class function only.

Day 3 Morning
  9. Inheritance

- Function overloading and default parameter does not support polymorphism.
$ cat main.cpp
#include <iostream>
using namespace std;
struct A{
virtual void func(int x){
cout<<"A::func"<<endl;
}
};
struct B:A{
void func(float y){
cout<<"B::func"<<endl;
}
};

int main(){
A* pa=new B;
pa->func(10); // resolves to A::func
return 0;
}

$ ./a.out
A::func

© www.minhinc.com
p66
Day 3 Morning
  9. Inheritance

-A publicly derived class inherits the interface of its base class. It has the same interface as its base class. In well designed class hierarchies object of a publicly derived class can be used wherever an object of the base
class is expected.
Classes derived using protected or private inheritance do not inherit the base class interface. Instead these derivations are often referred to as implementation inheritance. The derived class uses the inherited class in its implementation but does not expose the fact of the inheritance as part of its interface..

$ cat main.cpp
#include <iostream>
using namespace std;
class A{
public:
int pl;
private:
int pr;
};
class B:private A{ //implementation inheritance
public:
using A::pl; //still pl can be accessible
B(){pl=20;}
//using A::pr;//error
private:
//using A::pr;//error
};
int main(){
B b;
cout<<"B::pl"<<b.pl<<endl;
return 0;
}

$ ./a.out
B::pl20
© www.minhinc.com
p67
 
Day 3 Afternoon
  10. Generic Programming

Rather than each container class provide methods, a library provide methods that works on all sequential and associative containers.

- include <algorithm>
- include <numeric>

Functions available sort, find, accumulate, find_first_of, fill etc.

Day 3 Afternoon
  10. Generic Programming

Generic algorithms function takes both iterator and pointers as argument.
Iterator have pointer operator overloaded.

int search_value=42;
vector<int>::const_iterator result=find(vec.begin(),vec.end(),search_value);
cout<<"The value" << search_value
<< (result == vec.end() ? " not present " : " is present ") << endl;
list<int>::const_iterator result=find(lst.begin((),lst.end(),search_value);

int ia[6] = {27,210, 12, 47, 109, 83 };
int search_value=83;
int *result=find(ia,ia+6,search_value);
cout<<"The value"<<search_value
<<(result == ia+6  ? "is not present" : "is present")<<endl;

Day 3 Afternoon
  10. Generic Programming

read-only algorithms are only to read from the container and can not write to the container.

find();
accumulate();

int sum=accumulate(vec.begin(),vec.end(),42); // 42
               specifies initial value and int type
string sum=accumulate(v.begin(),v.end(),string("")); //
                string("") specifies string type

There are few algorithms which writes to the container.

Day 3 Afternoon
  10. Generic Programming

There are five iterator categories.
1)Input iterator - read, but not write, increment only
2)Output iterator - write but not read; increment only
© www.minhinc.com
p68
3)forward iterator - read and write; increment ony
4)bidirectional iterator - read and write; increment and decreament
5)random access iteratot - read and write; full iterarot arithmetic


Day 3 Afternoon
  10. Generic Programming

Generic algorithms does not change the container size. It is generic in
the sense it takes iterator of any type and then calls generic functions
on the iterator. It is an iterator which modifies the container

These iterator are bound to a container and can be used to insert elements
to the container.

Two types of inserter back_inserter and front_inserter.


----------------------      -----------------  push_back ----------- to -------------
| Generic algoritms | ----> | back_inserter |   o------  |iterator |--->| container |
| ex. fill_n        |       -----------------            -----------    -------------
----------------------

vector<int> vec;
fill_n(ack_inserter(vec),10,0); // appends 10 elements to vec

copy(lst.begin(),lst.end(),back_inserter(vec));

Day 3 Afternoon
  10. Generic Programming

ostream_iterators are used to write a sequence of value to a stream in much the same way that we might use and iterator to assign a sequence of values to the elements of a container.

ostream_iterator<string> out_iter(cout,"
");
istream_iterator<string> in_iter(cin),eof;
while(in_iter != eof)
*out_iter++ = *in_iter++;


Limitations of steam iterators
- It is not possible to read from an ostream_iterator and it not possible to write to an istream_iterator.
- Once we assign a value to an ostream_iterator, the write is committed
- There is no -> operator for ostream-iterator

Sorting input from console
istream_iterator<int. cin_it(cin);
istream_iterator<int> end_of_stream;
vector<int>(cin_it,end_of_stream);
sort(vec.begin((),vec.end9));
ostream_iterator<int> output(cout, " ");
unique_copy(vec.begin(),vec.end(),output);
© www.minhinc.com
p69
 
Day 4 Morning
  11. Operator overloading

- Its possible to overload operator and making it a member function.
- operator can be called in expression way or like a member function

#include <iostream>
using namespace std;
class mystring {
public:
mystring(const mystring& str) {
_val=str._val;
}
mystring(const char* val) {
_val=val;
}
mystring& operator+=(const mystring& val) {
_val=_val+val._val;
return *this;
}
const string& val() {
return _val;
}
private:
string _val;
};
mystring operator+(const mystring& left, const mystring& right) {
mystring tempstr(left);
tempstr+=right;
return tempstr;
}
int main(int argc, char *argv[]) {
mystring item="one";
item=item+"two";
item.operator+=("three");
cout<<"item : "<<item.val().c_str()<<endl;
return 0;
}

 - It makes classes object support operators and can be used in expression.
- operator to overload

+	-	*	/	%	^
&	|	~	!	,	=
<	>	<=	>=	++	--
<<	>>	==	!=	&&	||
+=	-=	/=	%=	^=	&=
|=	*=	<<=	>>=	[]	()
->	->*	new	new []	delete	delete []

- operators that cannot be overloaded
   ::	.*	.	?:

- Precautions
 - Overloaded Operators mush have an operand of Class Type
    int operator+(int, int); // error int not class type
 - Precedence and Associativity are Fixed
    x == y+z; // y+z would happen first followed by left to right associativity
 - Take care when overloading short circuit evaluation.
    & | && || ,
- Operator

© www.minhinc.com
p70
Day 4 Morning
  11. Operator overloading

- Two kinds of operator overloading
- As member function
  - The assignment(=), subscript ( [] ), call ( () ), and member access arrow (->)
  operators must be defined as members. Defining any of these operations as a
  nonmember function is flagged at compile time as an error.
  - Like = operator, compound assignment operators (+=, -=, *=, /=) ordinary
  ought to be members of the class. If not there then compiler will not generate
  any error if defined as non members.
  - Other operators that change the state of their object or that are closely tied
  to their given type - such as increment, decrement , and dereference -
  usually should be members of the class.
  - Operator returning lvalue
- As friend function or non member function
  - Symmetric operators, such as the arithmetic, equality, relational , and
  bitwise operators, are better defined as ordinary nonmember functions.
  - Operator return r-value better fits as non member. i.e. + operator.


Day 4 Morning
  11. Operator overloading

- Generally binary operators are non-member functions.
classA operator+(const classA &lhs, const classA &rhs);
classA operator-(const classA &lhs, const classA &rhs);
classA operator*(const classA &lhs, const classA &rhs);
classA operator/(const classA &lhs, const classA &rhs);

inline bool operator==(const classA &lhs, const classA &rhs);
inline bool operator!=(const classA &lhs, const classA &rhs);

#include <iostream>
using namespace std;
class Box{
double length;
double breadth;
double height;
public:
Box(int l=0,int b=0, int h=0):length(l),breadth(b),height(h){}
double volume(void){
return length * breadth * height;
}
Box operator+(const Box& b){
Box box;
box.length = this->length + b.length;
box.breadth = this->breadth + b.breadth;
box.height = this->height + b.height;
return box;
}
};
int main( ){
Box box1(10, 5, 2);
Box box2(4, 10, 4);
Box box3;
cout << "Volume of Box1 : " << box1.volume() <<endl;
cout << "Volume of Box2 : " << box2.volume() <<endl;
box3 = box1 + box2;
cout << "Volume of Box3 : " << box3.volume() <<endl;
return 0;
}

© www.minhinc.com
p71
Exercise - implement through += operator.

Day 4 Morning
  11. Operator overloading

- There are various relational operators supported by C++ language like (<, >, <=, >=, ==, etc.) which can be used to compare C++ built-in data types.

#include <iostream>
using namespace std;
class Distance {
int feet;
int inches;
public:
Distance(int f=0, int i=0) {
feet = f;
inches = f;
}
friend bool operator <(const Distance& dl, const Distance &dr);
};
bool operator <(const Distance& dl, const Distance &dr) {
if(dl.feet < dr.feet) {
return true;
}
if(dl.feet == dr.feet && dl.inches < dr.inches) {
return true;
}
return false;
}
int main()
{
Distance d1(11, 10), d2(5, 11);
if( d1 < d2 )   {
cout << "d1 is less than d2 " << endl;
}   else   {
cout << "d2 is less than d1 " << endl;
}
return 0;
}

Day 4 Morning
  11. Operator overloading

- The unary operators operate on a single operand.
  - The increment (++) and decrement (--) operators.
  - The unary minus (-) operator.
  - The logical not (!) operator.


- This operator appears on the left side of the object, as in !obj, -obj, and ++obj but sometime they can be used as postfix as well like obj++ or obj--.

#include<iostream>
using namespace std;
class Distance{
private:
int feet;
int inches;
public:
Distance(int f=0,int i=0){
feet = f;
inches = i;
}
int gfeet() {
return feet;
© www.minhinc.com
p72
}
int ginches() {
return inches;
}
Distance(const Distance& d) {
feet=d.feet;
inches=d.inches;
}
Distance operator- ()
{
feet = -feet;
inches = -inches;
return Distance(feet, inches);
}
Distance& operator++() {
if(++inches == 12) {
inches=0;
++feet;
}
return *this;
}

Distance operator++(int) {
Distance d(*this);
++*this;
return d;
}
};
int main()
{
Distance d1(11, 10), d2(-5, 11);
-d1;
cout<<"feet : inches "<<d1.gfeet()<<" : "<<d1.ginches()<<endl;
-d2;
cout<<"feet : inches "<<d2.gfeet()<<" : "<<d2.ginches()<<endl;
d1.operator++(0);
cout<<"feet : inches "<<d1.gfeet()<<" : "<<d1.ginches()<<endl;
d2.operator++();
cout<<"feet : inches "<<d2.gfeet()<<" : "<<d2.ginches()<<endl;
return 0;
}

Day 4 Morning
  11. Operator overloading

- Assignment operator can be of non class type.
- Assignment operator can be compound type.

#include <iostream>
using namespace std;
class classA {
public:
classA(){
_data="";
}
classA(const classA& c) {
cout<<"copy constructor"<<endl;
}

classA& operator=(const char* cp) {
cout<<"char pointer"<<endl;
_data+=cp;
return *this;
}
classA& operator=(const string& cs) {
cout<<"constant string"<<endl;
_data+=cs;
return *this;
}
classA& operator=(char c) {
cout<<"char"<<endl;
_data+=c;
return *this;
}
classA& operator+=(const classA& rhs) {
_data+=rhs._data;
return *this;
}
string& data() {
return _data;
© www.minhinc.com
p73
}
private:
string _data;
};
int main() {
classA cls;
cls = "one";
cls = string(":two");
cls=':';
classA rhs;
rhs="three";
cls+=rhs;
cout<<"cls data : "<<cls.data()<<endl;
return 0;
}
}

Day 4 Morning
  11. Operator overloading

- Classes that represent containers from which individual elements can be retrieved usually define the subscript operator, operator[];
- Subscript operator can be used to provide lvalue and rvalue;

int &const[](const size_t);
const int &operator[](const size_t) const;

#include <iostream>
using namespace std;
class classA {
public:
classA(){
_data="";
}
classA(const classA& c) {
cout<<"copy constructor"<<endl;
}
classA& operator=(const char* cp) {
cout<<"char pointer"<<endl;
_data+=cp;
return *this;
}
classA& operator=(const string& cs) {
cout<<"constant string"<<endl;
_data+=cs;
return *this;
}
classA& operator=(char c) {
cout<<"char"<<endl;
_data+=c;
return *this;
}
classA& operator+=(const classA& rhs) {
_data+=rhs._data;
return *this;
}
string& data() {
return _data;
}
private:
string _data;
};
int main() {
classA cls;
cls = "one";
cls = string(":two");
cls=':';
classA rhs;
rhs="three";
cls+=rhs;
cout<<"cls data : "<<cls.data()<<endl;
return 0;
}

© www.minhinc.com
p74
Day 4 Morning
  11. Operator overloading

 - A conversion operator defines a conversion that converts a value of a class type to some other type.

#include <iostream>
#include <stdexcept>
using namespace std;
class classA {
public:
classA(int i=0):_val(i) {
if(i<0 || i>255)
throw out_of_range("Bad classA initializer");
}
operator int() const {return _val;}
private:
std::size_t _val;
};
int main() {
classA *cls;
try {
cls=new classA(10);
}
catch(const exception& e) {
cout<<"exception cought : "<<e.what()<<endl;
return -1;
}
cout<<" cls value : "<<*cls;
delete cls;
return 0;
}

Day 4 Morning
  11. Operator overloading

using namespace std;
class classA {
public:
classA(int i=0) {
_val=i;
}
operator int() const {
return _val;
}
private:
size_t _val;
};
class classB {
public:
classB(int i=0) {
_val=i;
}
operator classA() const {return _val%256;}
private:
size_t _val;
};
void calc(int i) {
cout<<"calc(int) : "<<i;
}

int main() {
classB intval(1);
classA cls(intval);
calc(cls);
//calc(intval);
return 0;
}
© www.minhinc.com
p75
 
Day 4 Morning
  12. Templates

- Templates are the foundations of generic programming, which involves writing code in a way that is independent of any particular type.
- A template is a blueprint or formula for creating a generic class or a function. The library containers like iterators and algorithms are examples of generic programming and have been developed using template concept.
- There is a single definition of each container, such as vector, but we can define many different kinds of vectors for example, vector <int> or vector <string>.
- Templates can be used to define functions as well as classes


Day 4 Morning
  12. Templates

 - The general form of a generic class declaration is shown here:
template <class type> class class-name {
.
.
.
}

- Here, type is the placeholder type name, which will be specified when a class is instantiated. You can define more than one generic data type by using a comma-separated list.

#include <iostream>
#include <vector>
#include <cstdlib>
#include <string>
#include <stdexcept>
using namespace std;
template <class T>
class Stack {
private:
vector<T> elems;     // elements
public:
void push(T const&);  // push element
void pop();               // pop element
T top() const;            // return top element
bool empty() const{       // return true if empty.
return elems.empty();
}
};
template <class T>
void Stack<T>::push (T const& elem) {
elems.push_back(elem);
}
template <class T>
void Stack<T>::pop () {
if (elems.empty()) {
throw out_of_range("Stack<>::pop(): empty stack");
}
elems.pop_back();
}
template <class T>
T Stack<T>::top () const {
if (elems.empty()) {
throw out_of_range("Stack<>::top(): empty stack");
}
return elems.back();
}
© www.minhinc.com
p76
int main() {
try {
Stack<int>         intStack;  // stack of ints
Stack<string> stringStack;    // stack of strings
intStack.push(7);
cout << intStack.top() <<endl;
stringStack.push("hello");
cout << stringStack.top() << std::endl;
stringStack.pop();
stringStack.pop();
}
catch (exception const& ex) {
cerr << "Exception: " << ex.what() <<endl;
return -1;
}
}

- The general form of a template function definition is as following

template <class type> ret-type func-name(parameter list)
{
// body of function
}
template <typename T>
inline T const& Max (T const& a, T const& b)
{
return a < b ? b:a;
}

- Function templates parameters can be type parameter and non type parameter
- Type name string can be typename or class, it can be used interchangeably

template<class A, class U>
A func(A* array, U value) {
A::size_type *p; // misleading, if typename then p is declaration otherwise multiplication
}

template<class A, class U>
A func(A *array, U value) {
typename A::size_type *p;
}

#include <iostream>
#include <string>
using namespace std;
template <typename T>
inline T const& Max (T const& a, T const& b)
{
return a < b ? b:a;
}
int main ()
{
int i = 39;
int j = 20;
cout << "Max(i, j): " << Max(i, j) << endl;
double f1 = 13.5;
double f2 = 20.7;
cout << "Max(f1, f2): " << Max(f1, f2) << endl;
string s1 = "Hello";
string s2 = "World";
cout << "Max(s1, s2): " << Max(s1, s2) << endl;
return 0;
}

Day 4 Morning
  12. Templates

-The process of determining the types and values of the template arguments from the type of the function argument is called template argument deduction.
-If a template type is used as the type of more than one function parameter template type deduction must generate the same template argument type for each corresponding function argument.

template <typenaem T>
int compare (const T& v1, const T& v2){
© www.minhinc.com
p77
if(v1 < v2) return -1;
if(v2<v1) retrun 1;
return 0;
}
short si;
compare(si,1024);//error

- Limited conversions on type parameter arguments
Arguments are not converted to match an existing instantiations, instead a new instance is generated.

- In two cases new instance would not be generated
> const conversion: A function that takes a reference or pointer to a const can be called with reference or pointer to non const object respectively with generating a new instantiation.
> array or function to pointer conversions: if the template parameter is not a reference type then normal pointer conversion will be applied to argument of array or function type.

-Template argument deduction and function pointer

template<typename T>int compare(const T&, const T&);
int (*pf1)(const int&, const int&) = compare;

Day 4 Morning
  12. Templates

- When template function returns a type that differs from any used in the parameter it is required to override the template argument deduction mechanism and explicitly specify the types or values to be used for the template parameters.
template<class T1, class T2, class T3> T1 sum(T2,T3);
long val3=sum<long(i,lng);
long val3=sum<long,int,long>(i,lng);

Day 4 Morning
  12. Templates

- There are three scenarios when friends appear to a template class or template function.
> A friend declaration for an ordinary non template class of function, which grants friendship to the specific named class of function.

template <class type> class Bar{
 friend class A;
 friend void fcn();
};

> A friend declaration for a class template or function template, which grants access to all instances of the friend.

template<class type> class Bar{
template <class T> friend class Fool;
template <class T> friend void templ_frnl(const T&);
};

> A friend declaration that grants access only to a specific instance of a class or function template.


© www.minhinc.com
p78
template <class T> class Foo2;
template <class T> void templ_func2(const T&);
template <class Type> class Bar{
friend class Foo2<char*>;
frind void templ_fnc2<char*>(char* const &);
};

Day 4 Morning
  12. Templates

Redefinition of a class template or a member of a class template in which the template parameters are specified.

template<> int compare(const char*>(const char* const&, const char* const&);

- Difference in template specialization and normal function overloading is template type does not do type conversion (short to int to float etc..), if different types are there then new template instantiation happens.

- A program can not have both the explicit specialization and an instantiation for the same template with the same set of template arguments.

class template specialization
template<> class A<const char*> {
public:
 void push(const char*);
 ...
};

void A<const char*>::push(const char* val){
...
}
Specializing members but not the class
template<> void A(const char*>::push(const char *const& val){
...
}

Day 4 Morning
  12. Templates

- Template bloat occurs when compilers generate code for all templated function in each translation unit that use them. It should be resolved at link time though. New compilers does that.


Day 4 Morning
  12. Templates

- A type that holds an ordered collection of objects of a single type.  Elements in a sequential container are accessed by position. i.e 
std::list std::vector std::deque
© www.minhinc.com
p79

 
Day 4 Morning
  12. Templates

- A type that holds a collection of objects that supports efficient lookup by key. i.e. 
std::set, set::map,, std::multiset, std::multimap
© www.minhinc.com
p80
 
Day 4 Afternoon
  13. Exception handling

- An exception is a problem that arises during the execution of a program.  A C++ exception is a response to an exceptional circumstance that arises while a program is running, such as an attempt to divide by zero.
- Exceptions provide a way to transfer control from one part of a program to another. C++ exception handling is built upon three keywords: try, catch, and throw.
 - throw: A program throws an exception when a problem shows up. This is done using a throw keyword.
 - catch: A program catches an exception with an exception handler at the place in a program where you want to handle the problem. The catch keyword indicates the catching of an exception.
 - try: A try block identifies a block of code for which particular exceptions will be activated. It's followed by one or more catch blocks.

 - Assuming a block will raise an exception, a method catches an exception using a combination of the try and catch keywords. A try/catch block is placed around the code that might generate an exception. Code within a try/catch block is referred to as protected code.

try
{
   // protected code
}
catch( ExceptionName e1 ) {
   // catch block
}
catch( ExceptionName e2 ) {
   // catch block
}
catch( ExceptionName eN ) {
   // catch block
}


If an exception is not caught by any catch statement because there is no
catch statement with a matching type, the special function terminate will
be called.

Day 4 Afternoon
  13. Exception handling

- The process known as stack unwinding continues up the chain of nested function calls until a catch clause for the exception is found.
- During stack unwinding the function containing the throw and possibly other functions  in the call chain are exited prematurely.
- During stack unwinding destructors are called against local objects.
- Do not throw exception in destructor as there would be multiple throws to catch and would miss the genuine exception raised and may end in calling terminate function.

© www.minhinc.com
p81
Day 4 Afternoon
  13. Exception handling

Throwing Exceptions:
Exceptions can be thrown anywhere within a code block using throw statements. The operand of the throw statements determines a type for the exception and can be any expression and the type of the result of the expression determines the type of exception thrown.

double division(int a, int b) {
if( b == 0 ) {
throw "Division by zero condition!";
}
return (a/b);
}

Catching Exceptions
The catch block following the try block catches any exception.
try  {
  // protected code
}
catch( ExceptionName e )  {
// code to handle ExceptionName exception
}

- Above code will catch an exception of ExceptionName type.
- catch block should handle any type of exception that is thrown in a try block,
an ellipsis, ..., between the parentheses enclosing the exception declaration.

try
{
   // protected code
}catch(...)
{
  // code to handle any exception
}

#include <iostream>
using namespace std;

double division(int a, int b)
{
if( b == 0 )
{
throw "Division by zero condition!";
}
return (a/b);
}

int main ()
{
int x = 50;
int y = 0;
double z = 0;
try {
z = division(x, y);
cout << z << endl;
}catch (const char* msg) {
cerr << msg << endl;
}

return 0;
}

© www.minhinc.com
p82
Day 4 Afternoon
  13. Exception handling

Exception thrown can be caught through parent class reference.

Day 4 Afternoon
  13. Exception handling

If an exception is not caught by any catch statement because there is no catch statement with a matching type, the special function terminate will be called.

Day 4 Afternoon
  13. Exception handling

To handle an exception from the constructor initializer, we must write the constructor as a function try block.

template <class T> Handle<T>::Handle(T *p)
try : ptr(p),use(new size_t(1))
{
}catch(const std::bad_alloc &e)
{ handle_out_of_memor(e);}

- function try precedes the member initialization
- the catch clause can handle exceptions thrown either from within the member initialization list or from within the constructor body.


Day 4 Afternoon
  13. Exception handling

Exception specification follows the function parameter list.

void recoup(int) throw(runtime_error); // throws only runtime_error
void recoup(int) throw(); // does not throw any exception

- Derive class functions should be more restrictive in specification

struct base {
virtual std::string f3() throw(std::logic_error,std::runtime_error);
};
struct derived:base{
std::string f3() throw();//more restrictive
};
void compute(base* pb) throw(){
try{
© www.minhinc.com
p83
pb->f3();
}catch(const logic_error &le){}
  catch(const runtime_error &re){}
}

Day 4 Afternoon
  13. Exception handling

void (*pf)(int)throw(runtime_error);
void recoup(int)throw(runtime_error);
void (*pf1)(int)throw()=recoup; // more restrictive
© www.minhinc.com
p84
 
Day 5 Morning
  14. Memory Management

allocator class allocates and deallocates type aware memory.
allocator<T> a // allocator object named a that can allocate or
                  construct objects of type T.
a.allocate(n)  // Allocates row, un constructed memory to hold n objects
                  of type T.
a.deallocate(p,n) // Deallocates memory that held n objects of type
                     T starting at address contained in the T* pointer
                     named p. User should run destroy() prior to calling
                     deallocate in order to have destructor called.
a.construct(p, t) // constructs a new element in the memory pointed
                     to by the T* pointer p. The copy constructor of type
                     T is run to initialize the object from t.
a.destroy(p)      // runs destructor on the object pointed to by the T*
                     pointer p.
uninitialized_copy(b,e,b2); // copy source iterator b, e to dest. b2
uninitialized_fill(b,e,t); // copy source iterator t to dest b, e
uninitialized_fill_n(b,e,t,n); // copy source iterator t of size n to dest b,e

string *sp=new string("initialized");

new operator calls operator new to allocate the raw byte memory as against to typed memory in allocator allocate function.

Calls constructors to initialize the memory.
3) Return the pointer
delete sp;

1) calls the destructor.
2) calls operator delete to free the memory.
void *operator new(size_t);
void *operator new[](size_t);
void *operator delete(void*);
void *operator delete[](void*);

Day 5 Morning
  14. Memory Management

new when unsuccessful throws bad_alloc exception.

                 	   ----------------
                           |  exception   |
                           ----------------
                         /     /     \   \
                       /      /       \    \
        --------------      /           \     -------------
        |  bad_cast  |    /               \   | bad_alloc |
        --------------  /                   \ -------------
                      /                       \
                    /                           \
           -----------------                ----------------
           | runtime_error |                |  logic_error |
           -----------------                ----------------
                        |                     |
                        |                     |
   -----------------    |                     |    -----------------
   | overflow_error|----+                     +----|  domain_error |
   -----------------    |                     |     -----------------
                        |                     |
                        |                     |
   -----------------    |                     |    --------------------
   |underflow_error|----+                     +----|  invalid_argument|
   -----------------    |                     |    --------------------
                        |                     |
                        |                     |
© www.minhinc.com
p85
   --------------       |                     |    -----------------
   | range_error|-------+                     +----|  out_of_range |
   --------------                             |    -----------------
                                              |
                                              |
                                              |    -----------------
                                              +----|  length_error |
                                                   -----------------

- new when unsuccessful throws bad_alloc exception.
- Value initialized then built in types are initialized where as class types as per the argument. When no argument is passed then default constructor is called.

string *ps = new string() ; // default constructor
int *pi = new int(); // pi points to an int value-initialized to 0
int *pi = new int(210); // pi points to an int value-initialized to 210
class classA{
public:
classA(const char* name):_name(name){}
const char* name(){return _name.c_str();}
private:
string _name;
};
int main(int argc, char *argv[]) {
classA *pc=new classA("heapallocation");
cout<<pc->name()<<endl;
return 0;
}

- delete can not be used on a pointer that is not allocated through new
- delete can happen on NULL pointers.
- After deletion pointer can still be used but its illegal and undefined.
- Dynamic allocation to const objects uses new const statement
 - const int *pci = new const int(1024);
 - delete pci;

Day 5 Morning
  14. Memory Management

Allocate function of allocator<T> class allocate memory of type T.

template<class T>
struct vector{
vector():front(0),free(0),end(0){}
void push_back(const T&);
static std::allocator<T> alloc;
T* front;
T* free; // free node
T* end; // one past the end
};
template<T>
void push_back(const T& t){
if(free == end) remanage();
alloc.construct(free,t);//construct free from t
++free;
}

© www.minhinc.com
p86
Day 5 Morning
  14. Memory Management

void vector<T>::remanage(){
std::ptrdifff_t size=free-front;
T* newfront=alloc.allocate(2*max(size,1)); //allocate memory,
                      don't construct through calling copy constructor
uninitialize_copy(front,end,newfront);
for(T *p=front;p!=end;p++)
alloc.destry(p);
if(front) alloc.deallocate(front,end-front);
front=newfront;
free=front+size;
end=front+2*max(size,1);

Day 5 Morning
  14. Memory Management

Operator new is an operator which allocates memory in bytes rather than in object type size. It comes in two variations 
void *operator new(size_t)
and void
*operator new[](size_t)
void *operator new(size_t) // allocates memory of size_t bytes analogous to malloc
void *operator new[] (size_t) //allocate an array

T* newelements=alloc.allocate(newcapacity);
or
T* newelements=static_cast<T*>(operator new [] (capacity * sizeof(T)));

Operator delete deallocates memory.
void operator delete(void*); // free an object
void operator delete[](void*); // free an array allocated through operator new[]

alloc.deallocate(front,end-front); // argument is size/count
operator delete[](front); // argument is array pointer

Operator new and Operator delete are analogous to allocate and does not involve in constructing the free memory.

Day 5 Morning
  14. Memory Management

Placement new is analogous to allocator construct function. Placement new initializes the raw memory.
It can be used to initialize memory with default to any kind of constructor, where as construct from allocator can do only through copy constructor.

new (place_address) type
new (place_address) type (nitializer-list)
© www.minhinc.com
p87
allocator<string> alloc;
string *sp=alloc.allocate(2);

b and e are pair of iterators
new(sp) string(,b,e); // construct directly with constructing a temporary object
alloc.construct(sp+1, sting(*b,e)); // first create temporary object of
   // string(b,e) and then call copy constructor to create destred object at sp+1

Day 5 Morning
  14. Memory Management

Void *operator new[](size_t);
Void operator delelte[](void0

operator new[] and operator delete used to allocate memoryf or an array where as operator delete[] used to deallocate array.

int *pi=new int[20];
delete[] pi;

Day 5 Morning
  14. Memory Management

It can be used to initialize memory with default to any kind of constructor, where as construct from allocator can do only through copy constructor.
allocator<string> alloc;
string *sp=alloc.allocate(2);
b and e are pair of iterators
new(sp) string(,b,e); // construct directly with constructing a temporary object
alloc.construct(sp+1, sting(*b,e)); // first create temporary object of
         string(b,e) and then call copy constructor to create destred object at sp+1

Day 5 Morning
  14. Memory Management

A class can overload operator new and operator delete. In this fashion calling expression new and delete simply calls operator new and operator delete. operator new has to memory allocation and initialization and overloaded operator delete has to call destructor explicitly and then freeing the memory.

Overloading one of operator new or operator delete is an error.  Must overload both or none.

This scenario is used to have own memory manager where pool of memory is allocated once and then free is just returning to the pool and allocating is taking from the pool.
© www.minhinc.com
p88
In case of overloading operator new, default new expression can be called through scope resolution operator.

Type *p=::new Type;
::delete p;

Day 5 Morning
  14. Memory Management

Day 5 Morning
  14. Memory Management
© www.minhinc.com
p89
 
Day 5 Morning
  15. RTTI

- RTTI allows programs that uses pointer or references to base classes to retrieve the actual derived types of the objects to which these pointers or references refer.
- It is provided through two operators
1. The typeid operator, which returns the actual type of the object referred to by a pointer or a reference.
2. The dynamic_cast operator, which safely converts from a pointer or reference to a base type to a pointer or reference to a derived type.

- RTTI is computes at run time for classes which has virtual functions otherwise it compute at compile time.

- typeid operator
 - Scenario
  - If two objects needs to be compared for equality then what can be solution.
  - provide overloaded function like following

bool operator==(const Base&, const Base&);
bool operator==(const Derived&, const Derived&);
bool operator==(const Derived&, const Base&);
bool operator==(const Base&, const Derived&);

This list can grow exponentially if derived classes are more
 - Other solution can be to have equal virtual function and let derived class override it have have custom implementation. Problem with virtual equal function is that all derived class must have Base pointer or reference in the function parameter. This let to compare only Base class attributes.

 - The other solution is to have a class provided by the compiler which actually fetches the information regarding the object's class. This is type_info class. typeid operator would return object of type_Info class.

Day 5 Morning
  15. RTTI

- dynamic_cast
struct A{};
struct B{};
struct C:A,B{}

                                          vtble
A*,C*  ---->   +-----------+          +-----------+
               |   vptr    | -------->|           |
               +-----------+
               |A attribute|
               +-----------+
               |C attribute|
B* ------>     +-----------+--------->+-----------+
               |   vptr    |          |  thunk    |
               +-----------+          +-----------+
               |B attribute|
               +-----------+

B* b=new C;
C* c=dynamic_cast<C*>(b); // ok
C* c=static_cast<C*>(b);// error

- Dynamic casts are needed when we have a reference or pointer to a base class but need to perform operations from the derived class that are not part of the base class.
© www.minhinc.com
p90
- To get derived behaviour of a pointer to base is to provide a virtual function and get it implemented in derived class.

if (Derived *derivedPtr = dynamic_cast<Derived*>(baseptr) ) {
} else {
}
or
void f(const Base &b) {
try {
const Derived &d=dynamic_cast<const Derived&>(b);
} catch (bad_cast) { // throws bad_cast
}
}

Day 5 Morning
  15. RTTI

- type_info class provides following operation
t1 == t2 Returns true if the two type_info objects t1 and t2 refer to the same type; false otherwise.

t1 != t2 Returns true fi the two type_info objects t1 and t2 refer to different types; false otherwise

t.name() Returns a c-style character string that is printable version of the type name. Type names are generated in a system-dependent way.

t1.before(t2) Returns a bool that indicates whether t1 comes before t2.

The ordering imposed by before is compiler-dependent.

Base *bp;
Derived *dp;
if(typeid(*bp) == typeid(*dp)) {
}
if(typeid(*bp) == typeid(Derived)) {
}

if pointer type is used then RTTI resolves at compile time
if (typeid(bp) == typeid(Derived)) { // never equal
}

- If value of pointer p is 0, then typeid(*p) throws a bad_type exception provided p has virtual functions.
- Combining typeid and dynamic_cast

class Base {
friend bool operator==(const Base&, const Base&);
public:
protected:
virtual bool equal(const Base&, const Base&);
};
class Derived:public Base {
friend bool operator ==(const Base&, const Base&);
public:
private:
bool equal(const Base&) const;
};
bool operator==(const Base &lhs, const Base &rhs) {
return typeid(lhs) == typeid(rhs) && lhs.equal(rhs);
}

bool Derived::equal(const Base &rhs) const {
if(const Derived *dp=dynamic_cast<const Derived*>(&rhs) {
//do more stuff
} else
return false;
}
bool Base::equal(const Base &rhs) const {
//do some base comparision of attributes
}

© www.minhinc.com
p91
Day 5 Morning
  15. RTTI

static_cast just change the structure/variable type not changing the address. It is used mainly for reinterpreting a type to different type. ex.
struct A{}
struct B{}
void func(void *pv,int nump){
if (nump==1)
A* a=static_cast<A*>(pv);
else if(nump==2)
B* b=static_cast<B*>(pv);
}

So it is mainly used where source type is know in advance.

dynamic_cast is used only in polymorphism where secondary base class
pointer need to be converted primary base class or derive base class pointer.

Day 5 Morning
  15. RTTI
reinterpret_cast is used in low level conversions. Little or Big endian can be known through reinterpret_cast

unsigned int i=1;
--------                         --------
| 0x00 |                         | 0x10 |
--------                         --------
| 0x00 |                         | 0x00 |
--------                         --------
| 0x00 |                         | 0x00 |
--------                         --------
| 0x01 | < -- little endian      | 0x00 |   < -- big endian
--------                         --------

#include <iostream>
#include <string>
using namespace std;
int main(){
unsigned int i=1;
char *b=reinterpret_cast<char*>(&i); // most of the machine
                         // char* represented in little endian
if(b[0])
cout<<"little endian";
else
cout<<"big endian";
return 0;
}
© www.minhinc.com
p92
 
Day 5 Morning
  16. Modern C++ Ox,11x,14x,17x,20x versions

C++11 is the ISO C++ standard ratified in 2011. The previous standard is often referred to as C++98 or C++03; the differences between C++98 and C++03 are so few and so technical that they ought not concern users.

Day 5 Morning
  16. Modern C++ Ox,11x,14x,17x,20x versions

No special keyword or annotation is needed for a function in a derived class to override a function in a base class. For example:
struct B {
virtual void f();
virtual void g() const;
virtual void h(char);
void k();       // not virtual
};

struct D : B {
void f();       // overrides B::f()
void g();       // doesn't override B::g() (wrong type)
virtual void h(char);   // overrides B::h()
void k();       // doesn't override B::k() (B::k() is not
virtual)
};

This can cause confusion (what did the programmer mean?), and problems
if a compiler doesn't warn against suspicious code. For example,
* Did the programmer mean to override B::g()? (almost certainly yes)
* Did the programming mean to override B::h(char)? (probably not because of the redundant explicit virtual).
* Did the programmer mean to override B::k()? (probably, but that's not possible).

To allow the programmer to be more explicit about overriding, we now have the "contextual keyword" override:

struct D : B {
void f() override;      // OK: overrides B::f()
void g() override;      // error: wrong type
virtual void h(char);   // overrides B::h(); likely warning
void k() override;      // error: B::k() is not virtual
};

A declaration marked override is only valid if there is a function to override.
Override is only a contextual keyword, so you can still use it as an identifier:
int override = 7;       // not recommended

Override controls: final
Sometimes, a programmer wants to prevent a virtual function from being overridden. This can be achieved by adding the specifier final. For example:

struct B {
virtual void f() const final;   // do not override
virtual void g();
};
struct D : B {
void f() const;         // error: D::f attempts to override final B::f
void g();               // OK
};

Final can be added for internal purpose and external user should not override it.
© www.minhinc.com
p93
final is only a contextual keyword, so you can still use it as an identifier:
int final = 7;  // not recommended

Day 5 Morning
  16. Modern C++ Ox,11x,14x,17x,20x versions

C++ offers several ways of initializing an object depending on its type and the initialization context.

string a[] = { "foo", " bar" }; // ok: initialize array variable
vector<string> v = { "foo", " bar" }; // error: initializer list for non-aggregate vector
void f(string a[]);
f( { "foo", " bar" } ); // syntax error: block as argument

and
int a = 2;              // ''assignment style''
int aa[] = { 2, 3 };    // assignment style with list
complex z(1,2);         // ''functional style'' initialization
x = Ptr(y);             // ''functional style'' for conversion/cast/construction

and
int a(1);       // variable definition
int b();        // function declaration
int b(foo);     // variable definition or function declaration

It can be hard to remember the rules for initialization and to choose the best way.

The C++11 solution is to allow {}-initializer lists for all initialization:
X x1 = X{1,2};
X x2 = {1,2};   // the = is optional
X x3{1,2};
X* p = new X{1,2};

struct D : X {
D(int x, int y) :X{x,y} { /* ... */ };
};

struct S {
int a[3];
S(int x, int y, int z) :a{x,y,z} { /* ... */ }; // solution to old problem
};

Importantly, X{a} constructs the same value in every context, so that {}-initialization gives the same result in all places where it is legal.
For example:
X x{a};
X* p = new X{a};
z = X{a};         // use as cast
f({a});           // function argument (of type X)
return {a};       // function return value (function returning X)

Day 5 Morning
  16. Modern C++ Ox,11x,14x,17x,20x versions

Inherited constructors
struct B {
void f(double);
};
struct D : B {
void f(int);
};
B b;   b.f(4.5);        // fine
D d;   d.f(4.5);        // surprise: calls f(int) with argument 4

© www.minhinc.com
p94
In C++98, we can "lift" a set of overloaded functions from a base class into a derived class:
struct B {
void f(double);
};
struct D : B {
using B::f;     // bring all f()s from B into scope
void f(int);    // add a new f()
};

B b;   b.f(4.5);        // fine
D d;   d.f(4.5);        // fine: calls D::f(double) which is B::f(double)

class Derived : public Base {
public:
using Base::f;    // lift Base's f into Derived's scope -- works in C++98
void f(char);     // provide a new f
void f(int);      // prefer this f to Base::f(int)

using Base::Base; // lift Base constructors Derived's scope -- C++11 only
Derived(char);    // provide a new constructor
Derived(int);     // prefer this constructor to Base::Base(int)
// ...
};

If you so choose, you can still shoot yourself in the foot by inheriting constructors in a derived class in which you define new member variables needing initialization:

struct B1 {
B1(int) { }
};
struct D1 : B1 {
using B1::B1; // implicitly declares D1(int)
int x;
};
void test()
{
D1 d(6);        // Oops: d.x is not initialized
D1 e;           // error: D1 has no default constructor
}

You might remove the bullet from your foot by using a member-initializer:
struct D1 : B1 {
using B1::B1;   // implicitly declares D1(int)
int x{0};       // note: x is initialized
};
void test()
{
D1 d(6);        // d.x is zero
}

Day 5 Morning
  16. Modern C++ Ox,11x,14x,17x,20x versions

Consider:
template<class T, class U>
  ??? mul(T x, U y)
{
return x*y;
}

What can we write as the return type? It's "the type of x*y", of course, but how can we say that? First idea, use decltype:
template<class T, class U>
decltype(x*y) mul(T x, U y) // scope problem!
{
return x*y;
}

The solution is put the return type where it belongs, after the arguments:
template<class T, class U>
auto mul(T x, U y) -> decltype(x*y)
{
© www.minhinc.com
p95
return x*y;
}

We use the notation auto to mean "return type to be deduced or specified later."

The suffix syntax is not primarily about templates and type deduction,
it is really about scope.
struct List {
struct Link { /* ... */ };
Link* erase(Link* p);   // remove p and return the link before p
// ...
};
List::Link* List::erase(Link* p) { /* ... */ }

The first List:: is necessary only because the scope of List isn't entered until the second List::. Better:

auto List::erase(Link* p) -> Link* { /* ... */ }

Now neither Link needs explicit qualification.

Day 5 Morning
  16. Modern C++ Ox,11x,14x,17x,20x versions

A range for statement allows you to iterate through a "range", which is anything you can iterate through like an STL-sequence defined by a begin() and end(). All standard containers can be used as a range, as can a std::string, an initializer list, an array, and anything for which you define begin() and end(), e.g. an istream. For   example:

void f(vector<double>& v)
{
for (auto x : v) cout << x << '
';
for (auto& x : v) ++x;  // using a reference to allow us to change the value
}


You can read that as "for all x in v" going through starting with v.begin() and iterating to v.end(). Another example:

for (const auto x : { 1,2,3,5,8,13,21,34 }) cout << x << '
';

The begin() (and end()) can be a member to be called x.begin() or a free-standing function to be called begin(x). The member version takes precedence.

Day 5 Morning
  16. Modern C++ Ox,11x,14x,17x,20x versions

A lambda expression is a mechanism for specifying a function object. The primary use for a lambda is to specify a simple action to be performed by some function. For example:

vector<int> v = {50, -10, 20, -30};
std::sort(v.begin(), v.end());  // the default sort
// now v should be { -30, -10, 20, 50 }
// sort by absolute value:
std::sort(v.begin(), v.end(), [](int a, int b) { return abs(a)<abs(b); });
// now v should be { -10, 20, -30, 50 }
© www.minhinc.com
p96
A lambda expression can access local variables in the scope in which it is used. For example:
void f(vector<Record>& v)
{
vector<int> indices(v.size());
int count = 0;
generate(indices.begin(),indices.end(),[&count](){
return count++;
});

// sort indices in the order determined by the name field of the records:
std::sort(indices.begin(), indices.end(), [&](int a, int b) {
return v[a].name<v[b].name; });
// ...
}


We could have said that we wanted to "capture" only v, we could have said so: [&v]. Had we wanted to pass v by value, we could have said so: [=v]. Capture nothing is [], capture all by references is[&], and capture
all by value is [=].

If an action is neither common nor simple, use a named function object or function
void f(vector<Record>& v)
{
vector<int> indices(v.size());
int count = 0;
generate(indices.begin(),indices.end(),[&](){ return ++count; });

struct Cmp_names {
const vector<Record>& vr;
Cmp_names(const vector<Record>& r) :vr(r) { }
bool operator()(int a, int b) const { return vr[a].name<vr[b].name; }
};

// sort indices in the order determined by the name field of the records:
std::sort(indices.begin(), indices.end(), Cmp_names(v));
// ...
}

Day 5 Morning
  16. Modern C++ Ox,11x,14x,17x,20x versions
© www.minhinc.com
p97
 
Day 5 Afternoon
  17. Pointer to class member

Pointer to class member (method or attributes) are important in the sense it can be used as generic type at many places including function argument types.

Pointer to member is applicable only to non-static members.

Attribute has grammar like
<attribute type> <classname>::*

Methods has grammar like
<return type> (<classname>::*)(argments)

class filebuffer{
public:
typedef std::string::size_type index;
char get() const;
char get(index offset) const;
private:
std::string content;
index offsetpos;
index length;
};

string filebuffer::*pfb_conent=&filebuffer::content;
filebuffer::index filebuffer::*pfb_offset=&filebuffer::offsetpos;
Char (filebuffer::*pfb_get)(filebuffer::index) const=&filebuffer::get;


Typedef
typedef char (filebuf::*action)(filebuff::index) const;
filebuf& func(const filebuf&,action=&filebuf::get);

func(filebuf());
func(filebuf(),&filebuf::get);
action get=&filebuf::get;
func(filebuf(),get);

Day 5 Afternoon
  17. Pointer to class member

The pointer-to-member dereference operator (.*) fetches the member from an object or reference.

The pointer-to-member arrow operator (->*) fetches the member through a pointer to an object.

Calling methods

char (filebuffer::*pfbget)() const = &filebuffer::get;
filebuffer filebuf;
char c1=filebuf.get(); // normal call
char c2=(filebur::.*pfbget)(); // through pointer class member

filebuffer *pfilebuf=&filebuf;
char c3=(filebuf::->*pfbget)();

Calling data member

filebuf::index filebuf::*pindex=&filebuff::offsetpos;
filebuf::index pos1=filebuf.offsetpos;
filebuf::index pos2=filebuf.*pindex;
filebuf::index pos3=pfilebuf->*pindex;

© www.minhinc.com
p98
Day 5 Afternoon
  17. Pointer to class member

$cat main.cpp
#include <iostream>
struct robot{
void left(int dp){std::cout<<"robot::moved left, distance "<<dp<<std::endl;}
void right(int dp){std::cout<<"robot::moved right, distance "<<dp<<std::endl;}
void front(int dp){std::cout<<"robot::move front distance "<<dp<<std::endl;}
void back(int dp){std::cout<<"robot::moved back distance "<<dp<<std::endl;}
};

struct command{
typedef void (robot::*actiontype)(int);
command(robot *rp,actiontype actp,int dp);
void move();
robot *rbt;
int dist;
actiontype act;
};
command::command(robot *rp,actiontype actp,int dp){
rbt=rp;
act=actp;
dist=dp;
}

void command::move(){
(rbt->*act)(dist);
}
int main(int argc, char *argv[]){
robot *rbt=new robot;
int i=0;
command cmd[2]={command(rbt,&robot::left,4),command(rbt,&robot::right,6)};
for(i=0;i<2;i++)
cmd[i].move();
return 0;
}

$ g++ -o command main.cpp
$ ./command
robot::moved left, distance 4
robot::moved right, distance 6
© www.minhinc.com
p99
 
Day 5 Afternoon
  18. Nested class and volatile operator

Nested Classes
A class defined within another class is a nested class/type.
A nested class is visible only in enclosing class scope and not in scope where enclosing close is defined.

Enclosing class and nested class need to access each others member as independent classes. So nested class just scopes a class other wise there is other different when it is two different classes.

template<class type>class queue{
private:
struct queueitem{
queueitem(const type &);
type item;
aueueitem *next;
};
aueueitem *head;
aueueitem *tail;
};

template<class type>
queue<type>::queueitem::queueitem(const type &t):
                                item(t),next(0){}

Day 5 Afternoon
  18. Nested class and volatile operator

In case user of enclosing class need see the implementation of the nested class.
Forward declare the nested class.

template <class type> class queue{
private:
struct queueitem;
queueitem *head;
queueitem *tail;
};

template <class type>
struct queue<type>::queueitem{
queueitem(const type &t):item(t)<next(0){}
type item;
queueitem *next;
};

Day 5 Afternoon
  18. Nested class and volatile operator

Some variables value depends on hardware and can change externally. This makes value not to be optimized by the compiler. Volatile operator puts tag on variable so that compiler would not optimize the variable.

For example, for a machine with memory-mapped input/output, a pointer to a device register might be declared as a pointer to volatile, in order to prevent the compiler from removing apparently redundant references through the pointer.  Except that it should diagnose explicit attempts to change const objects, a compiler may ignore these qualifiers.


Port
---------------------------------------------
© www.minhinc.com
p100
| control register |     |  data register   |
---------------------------------------------

typedef short int control;
typedef short int data;
#define ENABLE 0x40
#define READY 0x80
typedef struct port port;
struct port
{
control c;
data d;
};
typedef struct ioport ioport;
struct ioport
{
port in, out;
};

//Using the declarations above, assign one memory mapped address to it
ioport *const pio = (ioport *)0xFF70;
// check if control register ready bit is ready for data to be written
while (pio->out.c & READY == 0)
;
//write carriage return
pio->out.d = '\r';
while (pio->out.c & READY == 0)
;
pio->out.d = '
';
//.Compiler start doing the optimization in following ways.
//Optimization

if (pio->out.c & READY == 0)
for (;;)
;
pio->out.d = '\r';
if (pio->out.c & READY == 0)
for (;;)
;
pio->out.d = '
';
Optimization
if (pio->out.c & READY == 0)
for (;;)
;
pio->out.d = '\r';
pio->out.d = '
';

//Further Optimization where '\r' is removed as redundant
if (pio->out.c & READY == 0)
for (;;)
;
pio->out.d = '
';

Solution
ioport volatile *const pio = (ioport *)0xFFA0;

In C+= volatile operator is similar to const where const and non-const variable can be assigned to a const variable. Volatile <--- const <--- normal , a non volatile variable can not be assigned to volatile

volatile int v;
int *ip=&v; // error
volatile int *ip=&v; //ok

Only volatile member functions may be called on volatile objects.

Synthesized copy constructor and assignment operator does not include volatile in the argument type. This makes volatile object not be copied. In case of volatile objects copy constructor and synthesized operator need to be declared explicitly.

Class A{
Public:
A(const volatile A&); // similar to const, copy from volatile object
A& operator=(volatile const A&); // copy from volatile object
A& operator=(volatile const A&) volatile; //copy from volatile to volatile object
};
© www.minhinc.com
p101