Some parts from beginning are written in my wiki.
07.05.2022:
Default constructor parameters
//copy constructor
//pass object by value
Player hero{"Hero", 100, 20};
void display_player(Player p)
{
}
display_player(hero);
//return object by value
Player enemy;
Player create_super_enemy(){
Player an_enemy{"Super enemy", 1000, 1000};
return an_enemy; //A copy of an_enemy is return
}
enemy = create_super_enemy();
//construct one object based on another
Player {"hero", 100,100};
Player another_hero{hero}; //A copy of hero is made
//declaring copy consturctor
Type::Type(const Type &source);
Player::Player(const Player &source);
Account::Account(const Account &source);
//Implementing copy constructor
Type::Type(const Type &source){
//code or initialization list to copy the object
}
Player
Player::Player(const Player &source)
:name{source.name},
health{source.heath},
xp{source.xp}{}
Smart Pointers:
Unique pointer: It take the full heap memory and works there
//unique_ptr - creating, initializing and using
{
std::unique_ptr<int> p1 {new int {100} };
std::cout<<*p1<<std::endl; //100
*p1=200;
std::cout<<*p1<<std::endl; //200
} //here it is automatically deleted
//unique pointer method
{
std::unique_ptr<int> p1 {new int {100}};
std::cout<<p1.get()<<std::endl; //0x567588
p1.reset(); //p1 is now nullptr
if(p1)
std::cout<<*p1<<std::endl; //won't execute
} //automatically deleted
//user defined class
{
std::unique_ptr<Account> p1 {new Account {"Larry"}};
std::cout<<*p1<<std::endl; //display account
p1->deposit(1000);
p1->withdraw(500);
}
unique_ptr -make_unique(C++14)
{
std::unique_ptr<int> p1 = make_unique<int> (100);
std::unique_ptr>Account> p2= make_unique<Account>("Curly", 5000);
auto p3=make_unique<Player>("Hero" 100, 100);
}//automatically deleted
#include<iostream>
#include<memory>
#include<vector>
#include "Account.h"
#inlcude "Checking_Account.h"
#include "Trust_Account.h"
#include "Savings_Account.h"
class Test
{
private:
int data;
public:
Test(): data{0} {std::cout<<"Test constructor("<<data<<")"<<std::endl;}
Test(int data):data(data) {std::cout<<Test constructor("<<data<<")<<std::endl; }
int get_data() const {return data;}
~Test(){std::cout<<"Test destructor("<<data<<")<<std::endl;}
};
using namespace std;
int main()
{
Test *t1=new Test{1000};
delete t1;
std::unique_ptr<Test> t1 {new Test(100}};
std::unique_ptr<Test> t2 = std::make_unique<Test>(1000);
return 0;
}
Shared pointer: It works on half of the heap memory
//shared ptr--creating,initializing and using
{
std::shared_ptr<int> p1{new int {100}};
std::cout<< *p1 <<std:.endl;
*p1=200;
std::cout <*p1<<std::endl;
};
Weak Pointer:
//Weak pointer, cicular pointer
#include<memory>
#include<iostream>
class B;
class A{
std::shared_ptr<B> b_ptr;
public:
void set_B(std::shared_ptr<B> &b){
b_ptr=b;
}
A() {cout<<"A constructor"<<endl; }
~A() {cout<<"A constructor"<<endl; }
};
class B{
std::shared_ptr<A> b_ptr;
public:
void set_B(std::shared_ptr<B> &b){
a_ptr=a;
}
B() {cout<<"B constructor"<<endl; }
~B() {cout<<"B constructor"<<endl; }
};
int main(){
shared_ptr<A> a = make_shared<A>();
shared_ptr<B> b=make_shared<B>();
a->set_B(b);
b->set_A(a);
return 0;
}
//operator overloading
what is operator overloading
copy and move semantics
Number result=multiply(add(a,b), divide(c,d));
using overloaded operators
::
:?
.*
.
sizeof
Operator Overloading:
Inheritance:
The project in codelite: DerivingOurFirstClass
//Inheritance
Inheritance is A relationship
Composition has A relationship
Composition use much more frequent than inheritance
//composition
class Person{
private:
std::string name; //has-a name
Account account; //has-a account
}
class Base{
//Base class members...
};
class Derived: access--specifier Base{
//Derived class members
};
Access specifier : private , public , protected
public is-a relationship
private and protected has-a relationship
C++ derivation syntax:
class Account{
};
class Savings_Account: public Account{
};
//C++ creating objects
Account account {};
Account *p_account = new Account();
account.deposit(1000.0);
p_account->withdraw(200.0);
delete p_account;
Savings_Account sav_account {};
Savings_Account *p_sav_account = new Savings_Account();
sav_account.deposit(1000.0);
p_sav_account->withdraw(200.0);
delete p_sav_account;
#ifndef ACCOUNT
code for that:
#include <iostream>
using namespace std;
class Base
{
// Note friends of Base has access to all
public:
int a {0};
void display() { std::cout << a <<"," << b << "," << c << endl; } // member method has access to all
protected:
int b { 0 };
private:
int c { 0 };
};
class Derived : public Base
{
// a will be public
// b will be protected
// c will not be accessible
public:
void access_base_members()
{
a = 100; // ok
b = 200; // Ok
// c=300; //not accessible
}
};
int main()
{
Base base1;
base1.a = 100; // ok
base1.b = 200; // compiler error
base1.c = 300; // compiler error
Derived d;
d.a = 100; // Ok
d.b = 200; // Error
d.c = 300; // Error
return 0;
}
Inherited Constructors and Destructors
//constructors and destructors
class Base{
public:
Base(){ cout<<"Base Constructor"<<endl; }
};
class Derived: public Base{
public:
Derived(){ cout<<"Derived Constructor"<<endl; }
};
//Constructor
Base base; //Base constructor
Derived derived; //Base constructor and Derived constructor have invoked
//Destructors
//class destrcutors are invoked in the reverse order as constructor
//the derived one need to destroy first
class Base{
public:
Base(){cout<<"Base constructor"<<endl;}
~Base(){cout<<"Base destructor"<<endl;}
};
class Derived: public Base{
public:
Derived(){cout<<"Derived constructor"<<endl;}
~Derived(){cout<<"Derived destructor"<<endl;}
}
Base base; //base constructor, base destructor
Derived derived; //base constructor, derived constructor, derived destructor, base desttuctor
//Now seeing in the live code
Passing arguments to base class constructors:
#include<iostream>
using namespace std;
class Base{
private:
int value;
public:
Base(): value{0} { cout<<"Base no -args Constructor"<<endl; }
Base(int x): value{x} {cout<<"Base(int) overloaded constructor"<<endl;}
~Base() {cout<<"Base destructor"<<endl;}
};
class Derived: public Base{
private:
int doubled_value;
public:
Derived(): Base {}, doubled_value {0} { cout<<"Derived Constructor"<<endl; }
Derived(int x): doubled_value{x*2} {cout<<"Derived(int) overloaded constructor"<<endl;}
~Derived() {cout<<"Derived constructor"<<endl;}
};
int main()
{
// Base b;
// Base b{100};
Derived d {1000};
return 0;
}
Copy/ Move constructors and operator with derived class:
Polymorphism:
//Fundamental to object orineted programming
//compile time == static binding
//run time == late-binding //dynamic binding
Polymorphism
Compile Time:
-Function overloading
-Operator overloading
Run-Time: //it is use in real life
-Function overriding
A non-polymorphic example. Static binding //it is not good practic
void display_count(const Account &acc){
acc.display();
}
Account a ;
display_account(a);
Savings b;
display_account(b);
Checking c;
display_account(c);
Trust d;
display_account(d);
Lambda Expressions:
//Stateless lambda expressions
[] () -> return_type specifiers {};
int x {10};
[] (int x ) {std::cout<<x;} (100);
const int n {3};
int nums n [10,20,30];
auto sum = [] (int nums [] , int n ){
int sum {0};
for (int i = 0; i<n; i++)
sum+=nums[i];
return sum;
};
std:.cout<<sum(nums,3);
//value parameter
[] (int x) {std::cout<<x;};
//reference parameter
[] (int &x) {std::cout<<x;};
int test_score1 {88};
int test_score2 {75};
auto bonus = [] (int *score1, int *score2, int bonus_points){
*score1+= bonus_points;
*score += bonus_points;
};
bonus(&test_score1, &test_score2, 5);
std::cout<<"test_score1:"<<test_Score1<<std::endl;
std::cout<<"test_score2:"<<test_Score2<<std::endl;
std::vector <int> test_scores {93,88,75,68,65};
auto bonus = [] (std::vector<int> &scores, int bonus_points){
for(int &score:scores)
score+=bonus_points;
}
bonus(test_scores,5);
std::cout<<"test_scores:"<<std::endl;
std::cout<<"test_scores[0]<<std::endl;
std::cout<<"test_scores[1]<<std::endl;
std::cout<<"test_scores[2]<<std::endl;