LPA Beginning C++ Programming From Beginner To Beyond SEP2024
LPA Beginning C++ Programming From Beginner To Beyond SEP2024
If you have any questions of queries, please add your feedback in the Q&A section of the course on Udemy.
Best regards,
Tim Buchalka
Learn Programming Academy
• Relevant
• Windows, Linux, Mac OSX, Photoshop, Illustrator, MySQL, MongoDB,
Game engines, more …
• Amazon, Apple, Microsoft, PayPal, Google, Facebook, MySQL, Oracle, HP, IBM, more…
• VR, Unreal Engine, Machine learning, Networking & Telecom, more…
• Powerful
• fast, flexible, scalable, portable
• Procedural and Object-oriented
•Section challenges
• Description
• Starting project
• Completed solution
•Quiz style
• Multiple choice
• Fill in blank
• Concept oriented vs. code oriented
return 0
• The compiler has recognized an issue with your code that could lead to a
potential problem
• It’s only a warning because the compiler is still able to generate correct
machine code
int miles_driven;
std::cout << miles_driven;
#include <iostream>
int main() {
int favorite_number;
std::cout << "Enter your favorite number between 1 and 100: ";
std::cin >> favorite_number;
std::cout << "No really!!, " << favorite_number << " is my favorite number!" <<std::endl;
return 0;
}
int main() {
int favorite_number;
std::cout << "Enter your favorite number between 1 and 100: ";
std::cin >> favorite_number;
std::cout << "No really!!, " << favorite_number << " is my favorite number!" <<std::endl;
return 0;
}
#include <iostream>
int main() {
int favorite_number;
std::cout << "Enter your favorite number between 1 and 100: ";
std::cin >> favorite_number;
std::cout << "No really!!, " << favorite_number << " is my favorite number!" <<std::endl;
return 0;
}
#include <iostream>
int main() {
int favorite_number;
std::cout << "Enter your favorite number between 1 and 100: ";
std::cin >> favorite_number;
std::cout << "No really!!, " << favorite_number << " is my favorite number!" <<std::endl;
return 0;
}
#include <iostream>
int main() {
int favorite_number;
std::cout << "Enter your favorite number between 1 and 100: ";
std::cin >> favorite_number;
std::cout << "No really!!, " << favorite_number << " is my favorite number!" <<std::endl;
return 0;
}
cout << "Enter your favorite number between 1 and 100: ";
cout << "Enter your favorite number between 1 and 100: ";
return 0;
}
#include <iostream>
#include “myfile.h”
#if
#elif
#else
#endif
/* This is a comment
that spans multiple lines.
All of these lines will be ignored by the compiler
*/
// I can call the function and use the value that is returns
#if
#elif
#else
#endif
#ifdef
#ifndef
#define
#undef
#line
#error
#pragma
return 0;
}
program.exe
return 0;
}
int main()
{
int favorite_number;
std::cout << "Enter your favorite number between 1 and 100: ";
return 0;
}
int main()
{
int favorite_number;
cout << "Enter your favorite number between 1 and 100: ";
return 0;
}
int main()
{
int favorite_number;
cout << "Enter your favorite number between 1 and 100: ";
return 0;
}
• Can be chained
cout << "data 1 is " << data1;
• Can be chained
cin >> data1 >> data2;
move 21 to age
int age;
age = 21; // Compiler error
age = 21;
VariableType VariableName;
int age;
double rate;
string name;
Account franks_account;
Person james;
Age int
age $age
_age 2014_age
My_age My age
your_age_in_2014 Age+1
INT cout
Int return
• Character types
• Integer types
• signed and unsigned
• Floating-point types
• Boolean type
• Examples:
sizeof(int)
sizeof(double)
sizeof(some_variable)
sizeof some_variable
• The climits and cfloat include files contain size and precision information about your
implementation of C++
INT_MAX
INT_MIN
LONG_MIN
LONG_MAX
FLT_MIN
FLT_MAX
. . .
#define pi 3.1415926
•The name of the array represent the location of the first element in the
array (index 0)
•The [index] represents the offset from the beginning of the array
•I have no way of knowing how many students will register next year
•Options:
•Pick a size that you are not likely to exceed and use static arrays
•Use a dynamic array such as vector
•An array that can grow and shrink in size at execution time
•Very efficient
•Can use lots of cool functions like sort, reverse, find, and more.
ARRAYS AND VECTORS
BEGINNING C++ PROGRAMMING
What is a Vector? S07-CPP-0120-2
Vectors
Declaring
• Arithmetic
• Equality
• Relational
• Logical
• Compound assignment
• Precedence
•The value of the rhs must be type compatible with the lhs
•The lhs must be assignable
expr1 == expr2
expr1 != expr2
100 == 200
num1 != num2
STATEMENTS AND OPERATORS
BEGINNING C++ PROGRAMMING
Testing for Equality S08-CPP-0160-1
Testing for Equality
The == and != operators
expr1 op expr2
• Sequence
• Ordering statements sequentially
• Selection
• Making decisions
• Iteration
• Looping or repeating
if (expr)
statement;
• Create a block of code by including more than one statement in code block { }
• Blocks can also contain variable declarations
• These variables are visible only within the block – local scope
•Once a match occurs all following case sections are executes UNTIL a
break is reached the switch complete
• Iteration or repetition
• Loops are made up a loop condition and the body which contains the
statements to repeat
Execute a loop:
• a specific number of times
• for each element in a collection
• while a specific condition remains true
• until a specific condition becomes false
• until we reach the end of some input stream
• forever
• many, many more
• while loop
• iterate while a condition remains true
• stop when the condition becomes false
• check the condition at the beginning of every iteration
• do-while loop
• iterate while a condition remains true
• stop when the condition becomes false
• check the condition at the end of every iteration
• break
• no further statements in the body of the loop are executed
• loop is immediately terminated
• Control immediately goes to the statement following the loop construct
• Character functions
• C-style Strings
• C++ Strings
•String literal
•sequence of characters in double quotes, e.g. “Frank”
•constant
•terminated with null character
•Copying
•Concatenation
•Comparison
•Searching
•and others
•integer
•float
•long
•etc.
Can compare:
two std::string objects
std::string object and C-syle string literal
std::string object and C-style string variable
object.substr(start_index, length)
object.find(search_string)
object.erase(start_index, length)
string s1 {"Frank"};
s1 += " James";
cout << s1 << endl; // Frank James
Many more…
string s1;
cin >> s1; // Hello there
// Only accepts up to the first space
cout << s1 << endl; // Hello
function_name(argument);
function_name(argument1, argument2, …);
void say_hello () {
cout << "Hello" << endl;
}
int main() {
say_hello();
return 0;
}
void say_hello () {
cout << "Hello" << endl;
}
int main() {
for (int i{1} i<=10; ++i)
say_hello();
return 0;
}
void say_world () {
cout << " World" << endl;
}
void say_hello () {
cout << "Hello" << endl;
say_world();
}
int main() {
say_hello();
return 0;
}
void say_hello () {
cout << "Hello" << endl;
say_world();
cout << " Bye from say_hello" << endl;
}
int main() {
say_hello();
cout << " Bye from main" << endl;
return 0;
}
void say_hello ()
{
cout << "Hello" << endl;
}
int function_name()
{
statements(s);
return 0;
}
int function_name(int a) {
statements(s);
return 0;
}
void function_name()
{
statements(s);
return; // optional
}
void say_hello() {
cout << "Hello" << endl;
}
int main() {
say_hello(); // OK
say_hello(100); // Error
cout << say_hello(); // Error
// No return value
return 0;
}
int main() {
int result {0};
result = add_numbers(100,200); // call
return 0;
}
say_hello("Frank");
int main() {
int actual {50};
cout << actual << endl; // 50
param_test(actual); // pass in 50 to param_test
cout << actual << endl; // 50 - did not change
return 0
}
• If a function does not return a value (void) then the return statement is optional
•Sometimes some of the arguments have the same values most of the time
•We can tell the compiler to use default values if the arguments are not supplied
int main() {
double cost {0};
cost = calc_cost(100.0, 0.06);
return 0;
}
BEGINNING C++ PROGRAMMING FUNCTIONS
Default Argument Values S11-CPP-0120-2
Default Argument Values
Example – single default argument
double calc_cost(double base_cost, double tax_rate = 0.06);
int main() {
double cost {0};
cost = calc_cost(200.0); // will use the default tax
cost = calc_cost (100.0, 0.08); // will use 0.08 not the defauly
return 0;
}
int main() {
double cost {0};
cost = calc_cost (100.0, 0.08, 4.25); // will use no defaults
cost = calc_cost(100.0, 0.08); // will use default shipping
cost = calc_cost(200.0); // will use default tax and shipping
return 0;
}
•A type of polymorphism
•We can have the same name work with different data types to execute similar
behavior
•The compiler must be able to tell the functions apart based on the
parameter lists and argument supplied
int main() {
cout << add_numbers(10,20) << endl; // integer
cout << add_numbers(10.0, 20.0) << endl; // double
return 0;
}
// Error
• Since the array name evaluates to the location of the array in memory – this address is
what is copied
• So the function has no idea how many elements are in the array since all it knows is the
location of the first element (the name of the array)
int main() {
int my_numbers[] {1,2,3,4,5};
print_array(my_numbers);
return 0;
}
int main() {
int my_numbers[] {1,2,3,4,5};
print_array(my_numbers, 5); / 1 2 3 4 5
return 0;
}
• We saw how this is the effect with array, but what about other variable types?
• The formal parameter will now be an alias for the actual parameter
int main() {
int number {1000};
scale_number(number); // call
cout << number << endl; // 100
return 0;
}
int main() {
int x{10}, y{20};
cout << x << " " << y << endl; // 10 20
swap(x, y);
cout << x << " " << y << endl; // 20 10
return 0;
}
int main() {
std::vector<int> data {1,2,3,4,5};
print(data); // 1 2 3 4 5
return 0;
}
void print(std::vector<int> v) {
for (auto num: v)
cout << num << endl;
}
int main() {
std::vector<int> data {1,2,3,4,5};
print(data); // 1 2 3 4 5
return 0;
}
int main() {
std::vector<int> data {1,2,3,4,5};
print(data); // 1 2 3 4 5
return 0;
}
• Global scope
• Function local variables are only active while the function is executing
• With nested blocks inner blocks can ‘see’ but outer blocks cannot ‘see’ in
• Visible to all parts of the program after the global identifier has been declared
int main() {
int result {0};
result = add_numbers(100,200); // call
return 0;
}
• Base case:
• factorial(0) = 1
• Recursive case:
• factorial(n) = n * factorial(n-1)
• Base case:
• Fib(0) = 0
• Fib(1) = 1
• Recursive case:
• Fib(n) = Fib(n-1) + Fib(n-2)
• To use the data that the pointer is pointing to you must know its type
• Inside functions, pointers can be used to access data that are defined outside the function.
Those variables may not be in scope so you can’t access them by their name
• If you don’t initialize a pointer to point to a variable or function then you should initialize
it to nullptr to ‘make it null’
int num{10};
cout << "Value of num is: " << num << endl; // 10
cout << "sizeof of num is: " << sizeof num << endl; // 4
cout << "Address of num is: " << &num << endl; // 0x61ff1c
int *p;
cout << "Value of p is: " << p << endl; // 0x61ff60 - garbage
cout << "Address of p is: " << &p << endl; // 0x61ff18
•Don’t confuse the size of a pointer and the size of what it points to
•All pointers in a program have the same size
•They may be pointing to very large or very small types
int *p1 {nullptr};
double *p2 {nullptr};
unsigned long long *p3 {nullptr};
vector<string> *p4 {nullptr};
string *p5 {nullptr};
score_ptr = &score; // OK
double *temp_ptr;
temp_ptr = nullptr;
*score_ptr = 200;
cout << *score_ptr << endl; // 200
cout << score << endl; // 200
temp_ptr = &low_temp;
name = "James";
*int_ptr = 100;
. . .
. . .
• If the pointer points to the same data type as the array element then the
pointer and array name can be used interchangeably (almost)
int_ptr++;
int_ptr--;
string s1 {"Frank"};
string s2 {"Frank"};
string s1 {"Frank"};
string s2 {"Frank"};
• Pointers to constants
• Constant pointers
*score_ptr = 86; // OK
score_ptr = &low_score; // ERROR
// *int_ptr = *int_ptr * 2;
}
int main() {
int value {10};
double_data( &value);
type *function();
// use it
int *dont_do_this () {
int size {};
. . .
return &size;
}
int *or_this () {
int size {};
int *int_ptr {&size};
. . .
return int_ptr;
}
• Dangling Pointers
• Leaking memory
. . .
• If you lose your pointer to the storage allocated on the heap you have not way
to get to that storage again
•Cannot be null
string name;
name = "Frank";
"Frank" = name; // "Frank" is NOT an l-value
string name;
name = "Frank"; // "Frank" is an r-value
int x {100};
int y {0};
int x {100};
square(num); // OK
• OO Programming limitations
• Inheritance
• can create new classes in term of existing classes
• reusability
• polymorphic classes
• Learning curve
• usually a steeper leaning curve, especially for C++
• many OO languages, many variations of OO concepts
• Design
• usually more up-front design is necessary to create good models and hierarchies
• Example classes
• Account
• Employee
• Image
• std::vector
• std::string
Account frank_account;
Account jim_account;
std::vector<int> scores;
std::string name;
class Class_Name
{
// declaration(s);
};
// methods
void talk(std::string text_to_say);
bool is_dead();
};
Account frank_account;
frank_account.balance;
frank_account.deposit(1000.00);
(*frank_account).balance;
(*frank_account).deposit(1000.00);
• Or use the member of pointer operator (arrow operator)
frank_account->balance;
frank_account->deposit(1000.00);
•private
•accessible only by members or friends of the class
•protected
•used with inheritance – we’ll talk about it in the next section
class Class_Name
{
public:
// declaration(s);
};
class Class_Name
{
private:
// declaration(s);
};
class Class_Name
{
protected:
// declaration(s);
};
class Player
{
private:
std::string name;
int health;
int xp;
public:
void talk(std::string text_to_say);
bool is_dead();
};
Player frank;
frank.name = "Frank"; // Compiler error
frank.health = 1000; // Compiler error
frank.talk("Ready to battle"); // OK
delete enemy;
class Account
{
private:
std::string name;
double balance;
public:
bool withdraw(double amount);
bool deposit(double amount);
};
Account frank_account;
frank_account.balance = 10000000.00; // Compiler error
frank_account.deposit(10000000.0); // OK
frank_account.name = "Frank’s Account"; // Compiler error
delete mary_account;
private:
double balance;
public:
void set_balance(double bal) {
balance = bal;
}
double get_balance() {
return balance;
}
};
private:
double balance;
public:
void set_balance(double bal);
double get_balance();
};
private:
double balance;
public:
void set_balance(double bal);
double get_balance();
};
#endif
class Account {
private:
double balance;
public:
void set_balance(double bal);
double get_balance();
};
#endif
class Account {
private:
double balance;
public:
void set_balance(double bal);
double get_balance();
};
BEGINNING C++ PROGRAMMING OOP - CLASSES AND OBJECTS
Implementing Member Methods S13-CPP-0140-7
Separating Specification from Implementation
Account.cpp
#include "Account.h"
double Account::get_balance() {
return balance;
}
int main() {
Account frank_account;
frank_account.set_balance(1000.00);
double bal = frank_account.get_balance();
• Can be overloaded
Player frank;
Player *enemy = new Player;
class Player
{
private:
std::string name;
int health;
int xp;
public:
// Overloaded Constructors
Player();
Player(std::string name_val);
Player(std::string name_val, int health_val, int xp_val);
};
BEGINNING C++ PROGRAMMING OOP - CLASSES AND OBJECTS
Overloading Constructors S13-CPP-0200-2
Constructors and Destructors
Overloaded Constructors
Player::Player() {
name = "None";
health = 0;
xp = 0;
}
Player::Player(std::string name_val) {
name = name_val;
health = 0;
xp = 0;
}
Better way:
Player::Player()
: name{"None"}, health{0}, xp{0} {
}
Better way:
Player::Player(std::string name_val)
: name{name_val}, health{0}, xp{0} {
}
Previous way:
Player::Player(std::string name_val, int health_val, int xp_val) {
name = name_val; // assignment not initialization
health = health_val;
xp = xp_val;
}
Better way:
Player::Player(std::string name_val, int health_val, int xp_val)
: name{name_val}, health{health_val}, xp{xp_val} {
}
Player::Player(std::string name_val)
: name{name_val}, health{0}, xp{0} {
}
Player::Player(std::string name_val)
: name{name_val}, health{0}, xp{0} {
}
Player::Player()
: Player {"None", 0, 0} {
}
Player::Player(std::string name_val)
: Player { name_val, 0, 0} {
}
}
Player empty; // None, 0, 0
Player frank {"Frank"}; // Frank, 0, 0
Player villain {"Villain", 100, 55}; // Villain, 100, 55
Player hero {"Hero", 100}; // Hero, 100, 0
void display_player(Player p) {
// p is a COPY of hero in this example
// use p
// Destructor for p will be called
}
display_player(hero);
Player create_super_enemy() {
Player an_enemy{"Super Enemy", 1000, 1000};
return an_enemy; // A COPY of an_enemy is returned
}
enemy = create_super_enemy();
• Problem: when we release the storage in the destructor, the other object still
refers to the released storage!
class Shallow {
private:
int *data; // POINTER
public:
Shallow(int d); // Constructor
Shallow(const Shallow &source); // Copy
Constructor
~Shallow(); // Destructor
};
Shallow::Shallow(int d) {
data = new int; // allocate storage
*data = d;
}
Shallow::~Shallow() {
delete data; // free storage
cout << "Destructor freeing data" << endl;
}
Shallow copy - only the pointer is copied - not what it is pointing to!
Problem: source and the newly created object BOTH point to the SAME data area!
int main() {
Shallow obj1 {100};
display_shallow(obj1);
// obj1’s data has been released!
obj1.set_data_value(1000);
Shallow obj2 {obj1};
cout << "Hello world" << endl;
return 0;
}
• Deep copy when you have a raw pointer as a class data member
Deep::Deep(int d) {
data = new int; // allocate storage
*data = d;
}
Deep::~Deep() {
delete data; // free storage
cout << "Destructor freeing data" << endl;
}
void display_deep(Deep s) {
cout << s.get_data_value() << endl;
}
When s goes out of scope the destructor is called and releases data.
No Problem: since the storage being releases is unique to s
obj1.set_data_value(1000);
Deep obj2 {obj1};
return 0;
}
• Copy constructors doing deep copying can have a significant performance bottleneck
• Copy elision – C++ may optimize copying away completely (RVO-Return Value
Optimization)
error: cannot bind non-const lvalue reference of type 'int&' to an rvalue of type 'int'
error: cannot bind rvalue reference of type 'int&&' to lvalue of type 'int'
Vector<Move> vec;
vec.push_back(Move{10});
vec.push_back(Move{20});
•Very efficient
Type::Type(Type &&source);
Player::Player(Player &&source);
Move::Move(Move &&source);
Move::Move(Move &&source)
: data{source.data} {
source.data = nullptr;
}
‘Steal’ the data and then null out the source pointer
Vector<Move> vec;
vec.push_back(Move{10});
vec.push_back(Move{20});
•Sometimes its useful to know if two objects are the same object
•We’ll use the this pointer again when we overload the assignment operator
• const-correctness
display_player_name(villain); // ERROR
class Player {
private:
. . .
public:
std::string get_name() const;
. . .
};
class Player {
private:
. . .
public:
std::string get_name() const;
// ERROR if code in get_name modifies this object
. . .
};
public:
static int get_num_players();
. . .
};
#include "Player.h"
int Player::num_players = 0;
int Player::get_num_players() {
return num_players;
}
int main() {
display_active_players();
Person p;
p.name = "Frank"; // compiler error - private
std::cout << p.get_name(); // compiler error - private
Person p;
p.name = "Frank"; // OK - public
std::cout << p.get_name(); // OK - public
•struct
•Use struct for passive objects with public access
•Don’t declare methods in struct
•class
•Use class for active objects with private access
•Implement getters/setters as needed
•Implement member methods as needed
•Function
•Can be regular non-member functions
•Can be member methods of another class
•Class
•Another class can have access to private class members
class Player {
friend void Other_class::display_player(Player &p);
std::string name;
int health;
int xp;
public:
. . .
};
class Other_class {
. . .
public:
void display_player(Player &p) {
std::cout << p.name << std::endl;
std::cout << p.health << std::endl;
std::cout << p.xp << std::endl;
}
};
class Player {
friend class Other_class;
std::string name;
int health;
int xp;
public:
. . .
};
•Using functions:
•‘arity’ cannot be changed (i.e. can’t make the division operator unary)
•Can’t overload operators for primitive type (e.g. int, double, etc.)
•[], (), ->, and the assignment operator (=) must be declared as member methods
•C++ provides a default assignment operator used for assigning one object to
another
Mystring s1 {"Frank"};
Mystring s2 = s1; // NOT assignment
// same as Mystring s2{s1};
s2 = s1; // assignment
delete [] str;
std::strcpy(str, rhs.str);
return *this;
// s1 = s2 = s3;
Mystring s1;
•If we have raw pointer we should overload the move assignment operator for
efficiency
if (this == &rhs)
return *this; // return current object
delete [] str;
•Steal the pointer from the rhs object and assign it to this->str
str = rhs.str;
rhs.str = nullptr;
return *this;
Mystring larry;
larry << cout; // huh?
Player hero;
hero >> cin; // huh?
• What is Inheritance?
• Why is it useful?
• Terminology and Notation
• Inheritance vs. Composition
• Deriving classes from existing classes
• Types of inheritance
• Protected members and class access
• Constructors and Destructors
• Passing arguments to base class constructors
• Order of constructor and destructors calls
• Redefining base class methods
• Class Hierarchies
• Multiple Inheritance
BEGINNING C++ PROGRAMMING INHERITANCE
Section Overview S15-CPP-0020-1
Inheritance
What is it and why is it used?
• Provides a method for creating new classes from existing classes
• The new class contains the data and behaviors of the existing class
•Account
• balance, deposit, withdraw, . . .
•Savings Account
• balance, deposit, withdraw, interest rate, . . .
•Checking Account
• balance, deposit, withdraw, minimum balance, per check fee, . . .
•Trust Account
• balance, deposit, withdraw, interest rate, . . .
•Inheritance
• Process of creating new classes from existing classes
• Reuse mechanism
•Single Inheritance
• A new class is created from another ‘single’ class
•Multiple Inheritance
• A new class is created from two (or more) other classes
•“Is-A” relationship
• Public inheritance
• Derived classes are sub-types of their Base classes
• Can use a derived class object wherever we use a base class object
•Generalization
• Combining similar classes into a single, more general class based on common attributes
•Specialization
• Creating new classes from existing classes proving more specialized attributes or operations
•Inheritance or Class Hierarchies
• Organization of our inheritance relationships
Classes:
•A
• B is derived from A
• C is derived from A
• D is derived from C
• E is derived from D
Classes:
• Person
• Employee is derived from Person
• Student is derived from Person
• Faculty is derived from Employee
• Staff is derived from Employee
• Administrator is derived from Employee
•Public Inheritance
• “is-a” relationship
• Employee ‘is-a’ Person
• Checking Account ‘is-a’ Account
• Circle “is-a” Shape
•Composition
• “has-a” relationship
• Person “has a” Account
• Player “has-a” Special Attack
• Circle “has-a” Location
has
Person Account
Employee Student
class Person {
private:
std::string name; // has-a name
Account account; // has-a account
};
•public
•Most common
•Establishes ‘is-a’ relationship between Derived and Base classes
account.deposit(1000.0);
p_account->withdraw(200.0);
delete p_account;
sav_account.deposit(1000.0);
p_sav_account->withdraw(200.0);
delete p_sav_account;
class Base {
protected:
// protected Base class members . . .
};
protected:
int b; // protected Base class members . . .
private:
int c; // private Base class members . . .
};
•The Base part of the Derived class MUST be initialized BEFORE the
Derived class is initialized
•The Derived part of the Derived class MUST be destroyed BEFORE the
Base class destructor is invoked
•How can we control exactly which Base class constructor is used during
initialization?
•We can invoke the whichever Base class constructor we wish in the initialization
list of the Derived class
Derived::Derived(int x)
: Base(x), {optional initializers for Derived} {
// code
}
BEGINNING C++ PROGRAMMING INHERITANCE
Passing Arguments to Base Class Constructors S15-CPP-0160-2
Constructors and Destructors
Constructors and class initialization
class Base {
int value;
public:
Base(): value{0} {
cout << "Base no-args constructor" << endl;
}
Base(int x) : value{x} {
cout << "int Base constructor" << endl;
}
};
•We can explicitly invoke the Base class versions from the Derived class
Base b;
b.deposit(1000.0); // Base::deposit
Derived d;
d.deposit(1000.0); // Derived::deposit
•A Department Chair
•Is-A Faculty and Faculty Administrator Staff
•Is-A Administrator
Department
Chair
class Department_Chair:
public Faculty, public Administrator {
. . .
};
•What is Polymorphism?
•Using base class pointers
•Static vs. dynamic binding
•Virtual functions
•Virtual destructors
•The override and final specifiers
•Using base class references
•Pure virtual functions and abstract classes
•Abstract classes as interfaces
•What is Polymorphism?
•Using base class pointers
•Static vs. dynamic binding
•Virtual functions
•Virtual destructors
•The override and final specifiers
•Using base class references
•Pure virtual functions and abstract classes
•Abstract classes as interfaces
• Polymorphism
• Compile-time / early binding / static binding
• Run-time / late binding / dynamic binding
• Runtime polymorphism
• Being able to assign different meanings to the same function at run-time
•Inheritance
•Base class pointer or Base class reference
•virtual functions
class Account {
public:
virtual void withdraw(double amount);
. . .
};
class Account {
public:
virtual void withdraw(double amount);
virtual ~Account();
. . .
};
• Useful when we pass objects to functions that expect a Base class reference
•Abstract class
• Cannot instantiate objects
• These classes are used as base classes in inheritance hierarchies
• Often referred to as Abstract Base Classes
•Concrete class
• Used to instantiate objects from
• All their member functions are defined
• Checking Account, Savings Account
• Faculty, Staff
• Enemy, Level Boss
• If the Derived class does not override then the Derived class is also abstract
• Used when it doesn't make sense for a base class to have an implementation
• But concrete classes must implement it
• Cannot be instantiated
• We can use pointers and references to dynamically refer to concrete classes derived from them
•These functions provide a general set of services to the user of the class
•Provided as public
•Custom deleters
•Ownership?
• Who owns the pointer?
• When should a pointer be deleted?
•Is Initialization
• The resource is acquired in a constructor
•Resource relinquishing
• Happens in the destructor
• Close the file
• Deallocate the memory
• Release the lock
•unique_ptr<T>
• Points to an object of type T on the heap
• It is unique – there can only be one unique_ptr<T> pointing to the object on the heap
• Owns what it points to
• Cannot be assigned or copied
• CAN be moved
• When the pointer is destroyed, what it points to is automatically destroyed
•shared_ptr<T>
•Points to an object of type T on the heap
•It is not unique – there can many shared_ptrs pointing to the same object on the
heap
•Establishes shared ownership relationship
•CAN be assigned and copied
•CAN be moved
•Doesn’t support managing arrays by default
•When the use count is zero, the managed object on the heap is destroyed
• weak_ptr<T>
• Points to an object of type T on the heap
• Does not participate in owning relationship
• Always created from a shared_ptr
• Does NOT increment or decrement reference use count
• Used to prevent strong reference cycles which could prevent objects from being deleted
• Exception safe
• when your code handles exceptions
• If a try block was used to then catch blocks are checked for a match
• If the stack is unwound back to main and no catch handler handles the exception
the program terminates
Best practice:
•throw an object not a primitive type
•throw an object by value
•catch an object by reference (or const reference)
•Method
• These work the same way as they do for functions as we’ve seen
•Constructor
• Constructors may fail
• Constructors do not return any value
• Throw an exception in the constructor if you cannot initialize an object
•Destructor
• Do NOT throw exceptions from your destructor
• Stream manipulators
• Sequence of bytes
• Boolean
• boolalpha , noboolalpha
• Integer
• dec, hex, oct, showbase, noshowbase, showpos, noshowpos, uppercase, nouppercase
• Floating point
• fixed, scientific, setprecision, showpoint, noshowpoint, showpos, noshowpos
• Others
• endl, flush, skipws, noskipws, ws
• Method version
• Reset to default
•Some of these manipulators affect only the next data element put on the stream
1. #include <fstream>
2. Declare an fstream or ifstream object
3. Connect it to a file on your file system (opens it for reading)
4. Read data from the file via the stream
5. Close the stream
• Always close any open files to flush out any unwritten data
1. #include <fstream>
2. Declare an fstream or ofstream object
3. Connect it to a file on your file system (opens it for writing)
4. Write data to the file via the stream
5. Close the stream
• Always close any open files to flush out any unwritten data
• Very powerful
1. #include <sstream>
2. Declare an stringstream, istringstream or ostringstream object
3. Connect it to a std::string
4. Read/write data from/to the string stream using formatted I/O
Code::Blocks
CLion
Xcode
• Extensible
•Algorithms
•Functions for processing sequences of elements from containers
(find, max, count, accumulate, sort, etc.)
•Iterators
•Generate sequences of element from containers
(forward, reverse, by value, by reference, constant, etc.)
•Associative containers
•set, multi set, map, multi map
•Container adapters
•stack, queue, priority queue
• Non-modifying
• Modifying
•Generic programming
“Writing code that works with a variety of types as arguments,
as long as those argument types meet specific syntactic and
semantic requirements”, Bjarne Stroustrup
•Function templates
•Class templates
• Blueprint
• Now the compiler can generate the appropriate function from the template
• Many times the compiler can deduce the type and the template parameter is
not needed
• Notice the type MUST support the > operator either natively or as an
overloaded operator (operator>)
• Let’s say we want a class to hold Items where the item has a name and an
integer
• But we’d like our Item class to be able to hold any type of data in addition to
the string
•Element should be
•Copyable and assignable (copy constructor / copy assignment)
•Moveable for efficiency (move Constructor / move Assignment)
•Works in reverse
•Last element is the first and first is the last
•++ moves backward, -- moves forward
•#include <algorithm>
#include <array>
• Fixed size
• Size must be known at compile time
#include <vector>
• Dynamic size
• Handled automatically
• Can expand and contract as needed
• Elements are stored in contiguous memory as an array
#include <deque>
• Dynamic size
• Handled automatically
• Can expand and contract as needed
• Elements are NOT stored in contiguous memory
• Rapid insertion and deletion at the front and back (constant time)
•Sequence containers
•Non-contiguous in memory
•Very efficient for inserting and deleting elements once an element is found
#include <list>
•Dynamic size
• Lists of elements
• list is bidirectional (doubly-linked)
#include <forward_list>
• Dynamic size
• Lists of elements
• list uni-directional (singly-linked)
• Less overhed than a std::list
• Reverse iterators not available. Iterators invalidate when corresponding element is deleted
•Associative containers
•Collection of stored objects that allow fast retrieval using a key
•STL provides Sets and Maps
•Usually implemented as a balanced binary tree or hashsets
•Most operations are very efficient
•Sets
•std::set
•std::unordered_set
•std::multiset
•std::unordered_multiset
#include <set>
•Ordered by key
#include <set>
•Sorted by key
#include <unordered_set>
#include <unordered_set>
•Associative containers
•Collection of stored objects that allow fast retrieval using a key
•STL provides Sets and Maps
•Usually implemented as a balanced binary tree or hashsets
•Most operations are very efficient
•Maps
•std::map
•std::unordered_map
•std::multimap
•std::unordered_multimap
#include <map>
• Similar to a dictionary
• Ordered by key
#include <map>
•Ordered by key
#include <unordered_map>
#include <unordered_map>
#include <stack>
#include <queue>
•Allows insertions and removal of elements in order from the front of the
container
#include <queue>
•Prior to C++ 11
•Function objects
•Function pointers
•Many times the classes and functions are far removed from where they are used
leading to modification, maintenance, and testing issues
• Enumerations in use
• As a result, many algorithms suffered from low readability and high numbers of
logic errors