207: Classes and OOP

Table of contents:
  1. Important points
  2. Class Syntax
  3. Define the class function outside the class
  4. Practice program 1
  5. Static data members and static functions
  6. Array of objects
  7. Passing objects as function arguments
  8. Friend function
  9. Constructors
  10. Constant keyword and const member function
  11. Operator overloading
  12. Inheritance
  13. Pointers





1. Important points:

  1. Classes don't take any memory.

  2. Class always ends with };
  3. Memory is only allocated when an object is created.

  4. unsigned int count; unsigned int means its value will always be non-negative.

  5. If 10 objects are made of a class, memory will be assigned to all 10 objects' variables and only one class' behaviors (functions) and static variables. The rest of the objects will share those behaviors and static variables.

  6. By default everything in the class is private.

  7. Static data:
    • We define the static variable outside the class because it is a class variable and you don't need an object to access the class variable.
    • Also, as it is a class variable, memory is only allocated to an object, not a class. So, you define it outside the class to allocate memory to it.
    • It is not global as a global variable (available to any code file linked to that file), rather, it is available in the single code file in which it is being used.

  8. Public functions are called manners or behaviors.

  9. We should not initialize data during the declaration. Instead, initialize it using a constructor and initializing list in order to establish a controlled, consistent, and valid initial state of objects.

  10. If you are making a constructor, then you must also make a default constructor. Otherwise, if you will make an object without arguments, the program will throw errors.

  11. When no copy constructor is found, the compiler supplies its own copy constructor.

  12. If you make an unsigned int variable and initialize it with 0, then subtract 1 from it and print the answer, you will get 4294967295 i.e. the highest value that can be stored in int because unsigned int does not give a negative value.

  13.  If you overload a constructor with default values in all the variables, it becomes a default constructor. Now if you also define a default constructor with no arguments, and make an object with no values passed to a constructor, compile-time error will occur.
    Complex(int x = 0, int y = 0) { real = x, imaginary = y;} // this is a default constructor






2. Class Syntax:

#include <iostream>
using namespace std;
class Distance
{
private:
    /*variable*/

public:
    /*function*/

};

int main()
{
    return 0;
}






3. Define the class function outside the class:

    If you declare and define a function in the class, it will be an inline function. So, in order to make a non-inline function, you can declare the function inside the body of the class and then define it outside the class using the scope resolution operator.
function_returnType className :: functionName(parameters)
Example:
#include <iostream>
using namespace std;
class Distance
{
private:
    int length, width;

public:
    void setData(int x, int y); // declaration
};

// function_returnType className :: functionName(parameters)
void Distance :: setData(int x, int y) // definition
{
    length = x;
    width = y;
}

int main()
{
    Distance d1;
    d1.setData(2, 3);
    return 0;
}






4. Practice program 1:

// Take a binary value input from the user and check if its valid or not
// The display it before and after ones compliment


#include <iostream>
using namespace std;
class Binary
{
private:
    string value;

public:
    void read();
    void check();
    void display();
    void ones_compliment();
};

void Binary ::read()
{
    cout << "Enter the Binary value: ";
    cin >> value;
}
void Binary ::check()
{
    for (int i = 0; i < value.size(); i++)
    {
        if (value[i] != '0' && value[i] != '1')
        {
            cout << "Invalid Input\n";
            exit(0);
        }
    }
    cout << "Your input seems to be valid\n";
}
void Binary ::display()
{
    cout << value << endl;
}
void Binary ::ones_compliment()
{
    for (int i = 0; i < value.size(); i++)
    {
        if (value[i] == '0')
        {
            value[i] = '1';
        }
        else if (value[i] == '1')
        {
            value[i] = '0';
        }
    }
}

int main()
{
    Binary b1;

    b1.read();
    b1.check();
    b1.display();
    cout << endl
         << "After ones compliment: ";
    b1.ones_compliment();
    b1.display();

    return 0;
}






5: Static Data member and static functions:

Static Data member:
  1. When a data member is declared static, only one copy of the data is maintained for all class objects.
  2. You have to declare it inside the class and define it outside the class.
  3. We define the static variable outside the class because it is a class variable and you don't need an object to access the class variable.
  4. Also as it is a class variable, memory is only allocated to objects, not a class. So, you define it outside the class to allocate memory to it.
  5. It is not global as a global variable (available to any code file linked to that file), rather, it is available in the single code file in which it is being used.
// syntax
#include <iostream>
using namespace std;
class Employee
{
private:
    static int count;

public:
};

int Employee ::count = 0;

int main()
{

    return 0;
}

Static function:
    This function is used to call access static data. You can call this function even if you haven't made any object. You cannot access non-static data through it.
// syntax
#include <iostream>
using namespace std;
class Employee
{
private:
    static int total_employees;

public:
    static void printTotal_employee();
};

int Employee ::total_employees = 0; // no static keyword in definition
void Employee ::printTotal_employee()    // no static keyword in definition
{
    cout << "Total no. of employees are: " << total_employees << endl;
}

int main()
{
    Employee ::printTotal_employee();

    return 0;
}

Example:

#include <iostream>
using namespace std;
class Employee
{
private:
    static int total_employees;
    string name;
    string id;

public:
    void printData();
    void setData();
    static void printTotal_employee();
};
int Employee ::total_employees = 0;
void Employee ::printData()
{
    cout << "Name: " << name << endl;
    cout << "Id: " << id << endl;
}
void Employee ::setData()
{
    cout << "Enter the name: ";
    cin >> name;
    cout << "Enter id: ";
    cin >> id;
    total_employees++;
}
void Employee ::printTotal_employee()
{
    cout << "Total no. of employees are: " << total_employees << endl;
}

int main()
{
    Employee umar, usman, abdullah;
    umar.setData();
    usman.setData();
    abdullah.setData();

    system("cls");

    umar.printData();
    cout << endl;
    usman.printData();
    cout << endl;
    abdullah.printData();
    cout << endl;
    cout << endl;
   
    Employee ::printTotal_employee();

    return 0;
}






6: Array of objects:

#include <iostream>
using namespace std;
class Employee
{
private:
    string name;
    string id;

public:
    void setData();
    void printData();
};
void Employee ::setData()
{
    cout << "Enter the name: ";
    cin >> name;
    cout << "Enter the id: ";
    cin >> id;
}
void Employee ::printData()
{
    cout << "Name: " << name << endl
         << "Id: " << id << endl;
}

int main()
{
    Employee emp[5];
    for (int i = 0; i < 5; i++)
    {
        system("cls");
        cout << "Enter the data of employee # " << i + 1 << endl;
        emp[i].setData();
    }

    system("cls");

    for (int i = 0; i < 5; i++)
    {
        emp[i].printData();
        cout << endl;
    }
   

    return 0;
}






7. Passing objects as function arguments:

#include <iostream>
using namespace std;
class Complex
{
private:
    int real_Part, imaginary_Part;

public:
    void setData();
    void setData_bySum_ofObjects(Complex x, Complex y);
    void printData();
};
void Complex ::setData()
{
    cout << "Enter the value of real part: ";
    cin >> real_Part;
    cout << "Enter the value of imaginary: ";
    cin >> imaginary_Part;
}
void Complex ::setData_bySum_ofObjects(Complex x, Complex y)
{
    real_Part = x.real_Part + y.real_Part;
    imaginary_Part = x.imaginary_Part + y.imaginary_Part;
}
void Complex ::printData()
{
    cout << "The complex no. is: " << real_Part << " + " << imaginary_Part << 'i' << endl;
}

int main()
{
    Complex num1, num2, num3;
    num1.setData();
    num2.setData();
    num3.setData_bySum_ofObjects(num1, num2);
   
    num1.printData();
    num2.printData();
    num3.printData();

    return 0;
}






8: Friend function:

  1. A friend function is simply a user-defined function that can access the private and protected data of a class.
  2. It is not in the scope of the class i.e. cannot be called from an object.
  3. Usually contains objects as arguments.
  4. Can be declared as friend in either public or private section of class.

#include <iostream>
using namespace std;
class Complex
{
private:
    int real_part, imaginary_part;

public:
    void setData(int x, int y);
    void printData();
    friend Complex sumComplex(Complex x, Complex y);
};
void Complex ::setData(int x, int y)
{
    real_part = x;
    imaginary_part = y;
}
void Complex ::printData()
{
    cout << "Complex no. is: " << real_part << " + " << imaginary_part << 'i' << endl;
}

Complex sumComplex(Complex x, Complex y); // declaration of friend function

int main()
{
    Complex num1, num2, num3;
    num1.setData(2, 3);
    num2.setData(4, 4);

    num3 = sumComplex(num1, num2);

    num1.printData();
    num2.printData();
    num3.printData();

    return 0;
}

Complex sumComplex(Complex x, Complex y) // definition of friend function
{
    Complex z;
    z.setData((x.real_part + y.real_part), (x.imaginary_part + y.imaginary_part));
    return z;
}


Make function of different classes a friend function:
  1. If you have to use a class' object that is made later in the program in another class, you can simply declare the class on top. This is a forward declaration.
  2. You can make only one function of the 2nd class, a friend of the 1st class (the function of the 2nd class can access the private data of the 1st class).
  3. You can declare a function and then define it later outside the class to remove the errors like this class is not defined yet.
#include <iostream>
using namespace std;

class Complex; // forward declaration

class Calculator
{
public:
    int add(int x, int y)
    {
        return x + y;
    }
    int sumReal_part(Complex, Complex);
};
class Complex
{
private:
    int real_part, imaginary_part;

public:
    void setData(int x, int y);
    friend int Calculator::sumReal_part(Complex x, Complex y); // only one function is made friend
};

int Calculator::sumReal_part(Complex x, Complex y)
{
    return (x.real_part + y.real_part);
}

void Complex ::setData(int x, int y)
{
    real_part = x;
    imaginary_part = y;
}

int main()
{
    Complex num1, num2, num3;
    num1.setData(2, 3);
    num2.setData(4, 4);

    Calculator calc;
    cout << "Sum of real parts: " << calc.sumReal_part(num1, num2) << endl;
    return 0;
}

Make an entire class friend:

Sometimes a large number of functions of one class is to be made friend of another class. In this case, you will have to declare each function as a friend. So, to avoid this, you can make the entire class a friend.

#include <iostream>
using namespace std;

class Complex; // forward declaration

class Calculator
{
public:
    int add(int x, int y)
    {
        return x + y;
    }
    int sumReal_part(Complex, Complex);
    int prodReal_part(Complex, Complex);
};
class Complex
{
private:
    int real_part, imaginary_part;

public:
    void setData(int x, int y);
    friend Calculator; // entire class is made friend
};

int Calculator::sumReal_part(Complex x, Complex y)
{
    return (x.real_part + y.real_part);
}
int Calculator::prodReal_part(Complex x, Complex y)
{
    return (x.real_part * y.real_part);
}

void Complex ::setData(int x, int y)
{
    real_part = x;
    imaginary_part = y;
}

int main()
{
    Complex num1, num2, num3;
    num1.setData(2, 3);
    num2.setData(4, 4);

    Calculator calc;
    cout << "Sum of real parts: " << calc.sumReal_part(num1, num2) << endl;
    cout << "Product of real parts: " << calc.prodReal_part(num1, num2) << endl;
    return 0;
}

Swapping values in two different classes using friend function:

#include <iostream>
using namespace std;
class Y;
class X
{
private:
    int dataX;
    friend void swap(X &x, Y &y);
public:
    void setData(int x);
    int printData();
};
class Y
{
private:
    int dataY;
    friend void swap(X &x, Y &y);
public:
    void setData(int x);
    int printData();
};

void X ::setData(int x)
{
    dataX = x;
}
void Y ::setData(int x)
{
    dataY = x;
}
int X ::printData()
{
    return dataX;
}
int Y::printData()
{
    return dataY;
}


void swap(X &x, Y &y);
int main()
{
    X numX;
    numX.setData(4);
    Y numY;
    numY.setData(3);

    cout << "Before swapping: " << endl << "X data: " << numX.printData() << endl
    << "Y data: " << numY.printData() << endl;

    swap(numX, numY);

    cout << "After swapping: " << endl << "X data: " << numX.printData() << endl
    << "Y data: " << numY.printData() << endl;

    return 0;
}

void swap(X &x, Y &y)
{
    int temp = x.dataX;
    x.dataX = y.dataY;
    y.dataY = temp;
}






9: Constructors:

  1. Constructor is a special member function having the same name as the class.
  2. It is automatically invoked when an object is created and it initializes the object.
  3. It should be declared in the public section of the class.
  4. They cannot return value as they don't have a return type not even void.
  5. A constructor that takes no arguments is known as a default constructor.
  6. It can have default arguments like Complex ::Complex(int x, int y){real = x; imaginary = y;}. Such a constructor is called the parameterized constructor.
  7. We cannot refer to their address.
  8. If you overload a constructor with default values in all the variables, it becomes a default constructor. Now if you also define a default constructor with no arguments, and make an object with no values passed to a constructor, compile-time error will occur.
    Complex(int x = 0, int y = 0) { real = x, imaginary = y;} // this is a default constructor
// syntax
#include <iostream>
using namespace std;
class Complex
{
private:
    int real, imaginary;

public:
    Complex();
    void printData();
};
Complex ::Complex()
{
    real = 0;
    imaginary = 0;
}
void Complex ::printData()
{
    if (imaginary >= 0)
    {
        cout << "Complex number: " << real << " + " << imaginary << 'i' << endl;
    }
    else
    {
        cout << "Complex number: " << real << " - " << imaginary * -1 << 'i' << endl;
        // * by -1 so that two - signs don't occur.
    }
}

int main()
{
    Complex num;
    num.printData();
    return 0;
}
You can also do this inside class like: 
Complex()
{
    real = 0;
    imaginary = 0;
}

Parameterized Constructor:
  1. Implicit constructor
  2. Explicit constructor
#include <iostream>
using namespace std;
class Complex
{
private:
    int real, imaginary;

public:
    Complex(int, int);
    void printData();
};
Complex ::Complex(int x, int y)
{
    real = x;
    imaginary = y;
}
void Complex ::printData()
{
    if (imaginary >= 0)
    {
        cout << "Complex number: " << real << " + " << imaginary << 'i' << endl;
    }
    else
    {
        cout << "Complex number: " << real << " - " << imaginary * -1 << 'i' << endl;
        // * by -1 so that two - signs don't occur.
    }
}

int main()
{
    Complex num1(4, 7); // implicit call
    num1.printData();

    Complex num2 = Complex(3, 9); // explicit call
    num2.printData();

    return 0;
}

Overloaded constructor:
Having more than one constructor with different parameters.

#include <iostream>
using namespace std;
class Complex
{
private:
    int real, imaginary;

public:
    Complex();
    Complex(int);
    Complex(int, int);
    void printData();
};
Complex ::Complex()
{
    real = 0;
    imaginary = 0;
}
Complex ::Complex(int x)
{
    real = x;
    imaginary = 0;
}
Complex ::Complex(int x, int y)
{
    real = x;
    imaginary = y;
}
void Complex ::printData() { cout << "Complex no. is: " << real << " + " << imaginary << 'i' << endl; }

int main()
{
    Complex num1, num2(5), num3(3, 7);
    num1.printData();
    num2.printData();
    num3.printData();
    return 0;
}

Constructor with default arguments:

#include <iostream>
using namespace std;
class Complex
{
private:
    int real, imaginary;

public:
    Complex(int, int);
    void printData();
};
Complex ::Complex(int x = 0, int y = 0) // default arguments
{
    real = x;
    imaginary = y;
}
void Complex ::printData() { cout << "Complex no. is: " << real << " + " << imaginary << 'i' << endl; }

int main()
{
    Complex num1, num2(5), num3(3, 7);
    num1.printData();
    num2.printData();
    num3.printData();
    return 0;
}

Copy constructor:
  1. Copy constructor creates a new object and initializes it by copying already existing object to it.
  2. If you don't make user user-defined copy constructor, the compiler will supply its own copy constructor.
  3. There are two methods of calling the copy constructor:
    • Complex num2(num1);
    • Complex num3 = num1;
#include <iostream>
using namespace std;
class Complex
{
private:
    int real, imaginary;

public:
    Complex();
    Complex(Complex &x);
    void printData();
};
Complex ::Complex()
{
    real = 0;
    imaginary = 0;
}
Complex ::Complex(Complex &x) // copy constructor (if you don't make this, program will still work fine)
{
    real = x.real;
    imaginary = x.imaginary;
}
void Complex ::printData() { cout << "Complex no. is: " << real << " + " << imaginary << 'i' << endl; }

int main()
{
    Complex num1;
    num1.printData();
    Complex num2(num1);
    Complex num3 = num1;
    return 0;
}


Constructor Initializer List:
  1. You should always initialize values in the same sequence with which the variables are declared while declaring class data members.
Syntax:
constructor_name(arguments) : variable(initializing_value_or_variable), variable(x)
{
    Constructor body
}
Example:
#include <iostream>
using namespace std;
class Complex
{
private:
    int real;
    int imaginary;

public:
    Complex() { real = 0; imaginary = 0; }

    Complex(int x = 0, int y = 0) : real(x), imaginary(y)
    {
        cout << "Complex number: " << real << " + " << imaginary << 'i' << endl;
    }
};
int main()
{
    Complex num1(3);
    return 0;
}

Valid constructor initializing lists:
  1. Complex(int x, int y) : real(x), imaginary(y)
    {
        cout << "Complex number: " << real << " + " << imaginary << 'i' << endl;
    }

  2. Arguments can be overloaded so even if the user passes only one value, the syntax will be valid.
    Complex(int x = 0, int y = 0) : real(x), imaginary(y)
    {
        cout << "Complex number: " << real << " + " << imaginary << 'i' << endl;
    }

  3. You can also perform operations while initializing.
    Complex(int x = 0, int y = 0) : real(x), imaginary(x + y)
    {
        cout << "Complex number: " << real << " + " << imaginary << 'i' << endl;
    }

  4. You can also initialize the second variable with the variable previously initialized.
    Complex(int x = 0, int y = 0) : real(x), imaginary(x + real)
    {
        cout << "Complex number: " << real << " + " << imaginary << 'i' << endl;
    }

  5. If you initialize one variable in the list and the second variable inside the body of the constructor, this will also be valid.
    Complex(int x = 0, int y = 0) : real(x)
    {
        imaginary = y;
        cout << "Complex number: " << real << " + " << imaginary << 'i' << endl;
    }

  6. If you didn't initialize in the sequence of declaration, it could cause problems like initializing with a garbage value.
    private:
        int real;
        int imaginary;
    public:
    Complex(int x = 0, int y = 0) : real(x), imaginary(y)
    {
        cout << "Complex number: " << real << " + " << imaginary << 'i' << endl;
    }






10. Const keyword and member functions:

  1. Const variable:
    You can initialize a const variable with any number, variable, or expression but you cannot change it afterwards.
        const int x = 1;
        const int y = x; const int z = x + y;
  2. Const argument of a function:
    If you are passing some argument to a function and you don't want its value to change somehow, make it const.
    void print(const int &x); // syntax
    Example:
    #include <iostream>
    using namespace std;
    void print(const int &x)
    {
        // x = 6; This will give compile time error
        cout << "Number: " << x << endl;
    }
    int main()
    {
        int num = 5;
        print(num);
        return 0; }
  3. Const data member of the class:
    Const data members cannot be initialized using a constructor. Instead, you can initialize it using the constructor initializing list.
    class Complex
    {
    private:
        const int real;
        const int imaginary;
    public:
        Complex() : real(0), imaginary(0) {}
        Complex(int x, int y): real(x), imaginary(y) {}
        void print(); };
  4. Const member function of a class:
    Const member function does not allow the change in the values of any data member of a class. However, you can change any temporary variable made inside the function or passed as an argument from the main().
    If you want arguments not to be changed, use const arguments.
    return_type function_name() const; // syntax
    Example:
    #include <iostream>
    using namespace std;
    class Complex
    {
    private:
        int real;
        int imaginary;

    public:
        Complex()
        {
            real = 0;
            imaginary = 0;
        }
        Complex(int x = 0, int y = 0)
        {
            real = x;
            imaginary = y;
        }
        void print() const;
    };
    void Complex ::print() const
    {
        // real = 6; this gives a compile-time error
        cout << "Complex number: " << real << " + " << imaginary << 'i' << endl;
    }
    int main()
    {
        Complex num1(3);
        num1.print();

        return 0;
    }


  5. Const object:
    Objects declared as constant cannot be modified. You can use this functionality when you make either a read-only object or you are passing the object to a function.
    #include <iostream>
    using namespace std;
    class Complex
    {
    private:
        int real;
        int imaginary;

    public:
        Complex()
        {
            real = 0;
            imaginary = 0;
        }
        Complex(int x = 0, int y = 0)
        {
            real = x;
            imaginary = y;
        }
        void print();
    };
    void Complex ::print()
    {
        real = 6;
        cout << "Complex number: " << real << " + " << imaginary << 'i' << endl;
    }
    int main()
    {
        const Complex num1(3);
        // num1.print(); this gives a compile-time error because of real = 6;

        return 0;
    }






11. Operator Overloading:

    Operator overloading is the changing of the way an operator works for user-defined objects and structures.

Example:
        If you want to increase a private variable of an object using the increment operator "++", a compile-time error will occur.
But if you define this functionality within the class, it will work just fine.

Operators that cannot be overloaded:
  1. Scope operator ==> ::
  2. Size of operator ==> sizeof()
  3. member selector ==> .
  4. member pointer selector ==> * 
  5. ternary operator ==> { ? : }
Syntax of operator overloading:

return_type operator ++(); // declaration
You can write any operator in place of ++
return_type Class_name ::operator++() { functionality } // definition


Overloading of prefix and postfix increment operator:

a) Prefix increment:
        By default, ++ operator in function declaration means prefix increment.
#include <iostream>
using namespace std;
class Counter
{
private:
    unsigned int count;

public:
    void operator++();
    void print() { cout << "Count: " << count << endl; }
};
void Counter ::operator++()
{
    count++;
}

int main()
{
    Counter c1;
    ++c1;
    c1.print();

    return 0;
}

b) Postfix increment operator overloading:
            In order to make the above program for postfix overloading, you will just have to pass int within the brackets () of the function. 
        This int is just a flag to show that the sign is a postfix operator. You will not pass anything.
#include <iostream>
using namespace std;
class Counter
{
private:
    unsigned int count = 0;

public:
    void operator++(int);
    void print() { cout << "Count: " << count << endl; }
};
void Counter ::operator++(int)
{
    count++;
}

int main()
{
    Counter c1;
    c1++;
    c1.print();

    return 0;
}

Example with return type counter:

#include <iostream>
using namespace std;
class Counter
{
private:
    unsigned int count = 0;

public:
    Counter() { count = 0; }
    Counter(int x) { count = x; }

    Counter operator++() { return Counter(++count); } // { count++; Counter temp(count); return temp; }
    Counter operator++(int) { return Counter(count++); }

    void print() { cout << "Count: " << count << endl; }
};

int main()
{
    Counter c1;
    Counter c2 = c1++;
    c2.print();

    Counter c3 = ++c1;
    c3.print();

    return 0;
}

Operators that can be overloadedExamples
Binary Arithmetic+, -, *, /, %
Unary Arithmetic +, -, ++, —
Assignment=, +=,*=, /=,-=, %=
Bitwise& , | , << , >> , ~ , ^
De-referencing(->)
Dynamic memory allocation,
De-allocation
New, delete 
Subscript[ ]
Function call ()
Logical &,  | |, !
Relational>, < , = =, <=, >=
Complex Example:
    Object on the left side of operator is calling object and on the right side is passed as argument.
// Create a class to represent a mathematical vector with private data members for
// its  components.  Define  constant  objects  and  constant  member  functions  to
// perform  vector  addition,  subtraction,  and  scalar  multiplication.  Implement
// getter and setter functions for the vector components

#include <iostream>
using namespace std;
class Vector
{
private:
    float X;
    float Y;
    float Z;

public:
    // constructors
    Vector() : X(0), Y(0), Z(0) {}
    Vector(float x = 0, float y = 0, float z = 0) : X(x), Y(y), Z(z) {}

    void printVector(string x) const { cout << x << '(' << X << ", " << Y << ", " << Z << ')' << endl; }

    // overloaded operators
    Vector operator+(const Vector &second) const;
    Vector operator-(const Vector &second) const;
    Vector operator*(const float &second) const;
};
Vector Vector ::operator+(const Vector &second) const { return Vector(X + second.X, Y + second.Y, Z + second.Z); }
Vector Vector ::operator-(const Vector &second) const { return Vector(X - second.X, Y - second.Y, Z - second.Z); }
Vector Vector ::operator*(const float &second) const { return Vector(X * second, Y * second, Z * second); }

int main()
{
    const Vector vec1(1, 2, 3), vec2(4, 5, 6);
    const int scalar = 5;
    vec1.printVector("Vector 1: ");
    vec2.printVector("Vector 2: ");

    Vector sum = vec1 + vec2; // vec1 is calling object and vec2 is passed as argument
    sum.printVector("Resultant vector after vector sum: ");

    Vector diff = vec1 - vec2;
    diff.printVector("Resultant vector after vector difference: ");

    Vector multiplication = vec1 * scalar;
    multiplication.printVector("Resultant vector after vector multiplication: ");

    return 0;
}







12: Inheritance:

            In C++, inheritance is a process in which one object acquires all the properties and behaviors of its parent object automatically.

Advantage:

Code reusability: Now you can reuse the members of your parent class. So, there is no need to define the member again. So less code is required in the class.

Base Class: A base class is also called a parent class or superclass. 

Derived Class: A class that is created from an existing class.

Syntax of derived class: 

class {{derived_class_name}} : {{visibility-mode}} {{base_class_name}}  
{  
    // body of the derived class.  
};

Visibility mode: 
The visibility mode specifies whether the features of the base class are publicly inherited or privately inherited. It can be public or private.

  1. In C++, the default mode of visibility is private.
  2. The private members of the base class are never inherited.

  3. When the base class is privately inherited by the derived class, public members of the base class become the private members of the derived class. Therefore, the public members of the base class are inaccessible by the objects but accessible by the member functions of the derived class.

  4. When the base class is publicly inherited by the derived class, public members of the base class also become the public members of the derived class. Therefore, the public members of the base class are accessible by both objects and member functions of the base class.

Types:

  • Single inheritance
  • Multiple inheritance
  • Hierarchical inheritance
  • Multilevel inheritance
  • Hybrid inheritance

(a) Single inheritance:

            Single inheritance is defined as the inheritance in which a derived class is inherited from only one base class.

C++ Inheritance

Where 'A' is the base class, and 'B' is the derived class.

Example 1:

// Make class Person and inherit it into Student. Now program such that if you set data of student,
// data of person is also set and if you display data of student, data of person is also displayed.

#include <iostream>
using namespace std;

class Person
{
private:
    string id;
    string name;

public:
    Person(string x = "non", string y = "non") { id = x, name = y; }
    void set_Person();
    void display_Person();
};
void Person ::set_Person()
{
    cout << "Enter name: ";
    getline(cin >> ws, name);
    cout << "Enter id: ";
    getline(cin >> ws, id);
}
void Person ::display_Person()
{
    cout << "Name: " << name << "\nId: " << id << endl;
}
// <---------------------------------------------------------------->

class Student : public Person
{
private:
    string course;
    int fee;

public:
    Student(string x = "BSCS", int y = 0) { course = x, fee = y; }
    void set_Student();
    void display_Student();
};
void Student ::set_Student()
{
    set_Person();
    cout << "Enter course name: ";
    getline(cin >> ws, course);
    cout << "Enter fee: ";
    cin >> fee;
}
void Student ::display_Student()
{
    display_Person();
    cout << "Course: " << course << "\nFee: " << fee << endl;
}

int main()
{
    Student s1("BSSE");
    s1.set_Student();
    system("cls");
    s1.display_Student();
    return 0;
}

Example 2:

//Make class Person and inherit it into Student. Now in main make object of Student and pass arguments to
//data members of both parent and child using constructor. Now display student and parent with single display

#include <iostream>
using namespace std;
class Person
{
private:
    string name, id;

public:
    Person(string n = "", string i = "") { name = n, id = i; }
    void display_Person() { cout << "Name: " << name << "\nId: " << id << endl; }
};

// derived class start
class Student : public Person
{
private:
    string rollno, course;

public:
    // call the constructor of parent using initializer list
    Student(string n="", string i="", string r="", string c=""): Person(n,i) {  rollno = r, course = c; }
    void display_Student()
    {
        display_Person();
        cout << "Roll no. " << rollno << "\nCourse: " << course << endl;
    }
};

int main()
{
    Student s1("Umar", "001", "007", "BSCS");
    s1.display_Student();
    return 0;
}

Visibility:

Public: Visible in the main via object and visible in the inherited class.
Protected: Visible only in inherited class. Invisible in main via object.

Base class visibilityDerived class visibility
PublicPrivateProtected
Private membersNot InheritedNot InheritedNot Inherited
Protected membersProtectedPrivateProtected
Public membersPublicPrivateProtected

  • You can never access private members of the base class. Not in the derived class and not even in the main using object. You can only access them within the public member functions of the base class.

  • You can access protected members of the base class within the derived class but you can never access them in the main using the object of derived class.

  • You can access public members of the base class within the derived class and also in the main using the object of the base class.

Virtual and Override:

  1. Virtual: You use 'virtual' keyword with the function in the base class that is to be overridden in the derived class
  2. Override: You use 'override' keyword with the function that is being overridden in the derived class.
  3. This shows an error during compile-time when the names of virtual and override functions are not same.
  4. Example:
    class base
    {
    public:
        virtual void print() { cout << "This is a base function\n"; }
    };

    class derived : public base
    {
    public:
        void print() override { cout << "This is an overridden function\n"; }
    };
Practice 1:
// Write a C++ program to demonstrate single inheritance by creating a base class "Circle" with a member
// function to calculate the area of circle and a derived class "new_Circle" to calculate the area of a circle
// if radius is positive and print a messege if radius is negative.

#include <iostream>
using namespace std;
class Circle
{
protected:
    float radius;

public:
    Circle(float rad = 0) { radius = rad; }
    virtual float calc_Area();
};
float Circle ::calc_Area() { return (3.14 * radius * radius); }

class new_Circle : public Circle
{
public:
    new_Circle(float rad = 0) { radius = rad; }
    float calc_Area() override;
};
float new_Circle ::calc_Area()
{
    if (radius < 0)
    {
        cout << "Radius should not be negative\n";
        return 0.0;
    }
    else
    {
        return (3.14 * radius * radius);
    }
}

int main()
{
    new_Circle c1(5.4);
    cout << "Area of circle: " << c1.calc_Area() << endl;
    return 0;
}

Practice 2:
// Create a base class "Person" with attributes like name and age.
// Derive a class "Student" from "Person" and add attributes like roll number and grade.
// Write a program to input and display the details of a student.

#include <iostream>
using namespace std;
class Person
{
private:
    string name;
    int age;

public:
    Person(string, int);
    virtual void display_Person();
};
Person ::Person(string n = "", int a = 0) { name = n, age = a; }
void Person ::display_Person() { cout << "Name: " << name << "\nAge: " << age << endl; }

// derived class
class Student : protected Person
{
private:
    string rollno;
    char grade;
public:
    Student(string, int, string, char);
    void display_Person() override;
};
Student ::Student(string n = "", int a = 0, string r = "", char g = 0) : Person(n, a)
{
    rollno = r;
    grade = g;
}
void Student ::display_Person()
{
    Person::display_Person();
    cout << "Roll no. " << rollno << endl;
    cout << "Grade: " << grade << endl;
}


int main()
{
    Student s1("Dev", 20, "007", 'A');
    s1.display_Person();
    return 0;
}

Practice 3:
        See blogpost 213 - 219: click here


Ambiguity 1:

Ambiguity occurs when a class inherits a function of same name from 2 different classes. Now if the derived class calls that function of base the compiler will throw an error because it does not know the function from which class are you talking about.

#include <iostream>
using namespace std;

class Base1
{
public:
    void display() { cout << "Call from base class # 1\n"; }
};

class Base2
{
public:
    void display() { cout << "Call from base class # 2\n"; }
};

class Derived : public Base1, public Base2
{
public:
    void print() { cout << "I am derived class\n"; }
};


int main()
{
    Derived o1;
    o1.display(); // this will give error
    return 0;
}

Solution:

This can easily be solved by using the scope resolution operator :: 

ObjectName.ClassName::FunctionName();


#include <iostream>
using namespace std;

class Base1
{
public:
    void display() { cout << "Call from base class # 1\n"; }
};

class Base2
{
public:
    void display() { cout << "Call from base class # 2\n"; }
};

class Derived : public Base1, public Base2
{
public:
    void print() { cout << "I am derived class\n"; }
};


int main()
{
    Derived o1;
    o1.Base1::display(); // this will give error
    return 0;
}

If derived class also has a function with same name, there will be no ambiguity because compiler will run the function of derived class.

#include <iostream>
using namespace std;

class Base1
{
public:
    void display() { cout << "Call from base class # 1\n"; }
};

class Base2
{
public:
    void display() { cout << "Call from base class # 2\n"; }
};

class Derived : public Base1, public Base2
{
public:
    void display() { cout << "I am derived class\n"; }
};


int main()
{
    Derived o1;
    o1.display(); // this will give error
    return 0;
}


Ambiguity # 2 (Diamond Problem):

The diamond problem The diamond problem occurs when two superclasses of a class have a common base class and compiler does not know which from which superclass should derived class is calling base class.

#include <iostream>
using namespace std;
class Base1
{
protected:
    int value = 0;
    int getValue() { return value; }
};

class Inter1 : public Base1
{
public:
    Inter1() { value = 1; }
};

class Inter2 : public Base1
{
public:
    Inter2() { value = 2; }
    // int getValue() { return value; }
};

class Derived : public Inter1, public Inter2
{
public:
    // Problem:
    // void printData() { cout << "The value in Base class is: " << getValue() << endl; } // here         we are getting getvalue() function from both Inter1 and Inter2. So the compiler does not
        know from which class should I call it. This is diamond problem

    // Solution:
    void printData() { cout << "The value in Base class is: " << Inter1::getValue() << endl; } // Now compiler knows
    //  which from which class should it call getValue() function.
};

int main()
{
    Derived var;
    cout << "Hello";
    var.printData();

    return 0;
}

Now in the above solution, two copies of the same base class were made and only one was called. But if you want that only one copy of based class is formed, you can use virtual inheritence.

Virtual inheritance that ensures only one copy of a base class's member variables are inherited by grandchild-derived classes.

#include <iostream>
using namespace std;
class Base1
{
protected:
    int value = 0;
    int getValue() { return value; }
};

class Inter1 : virtual public Base1
{
public:
    Inter1() { value = 1; }
};

class Inter2 : virtual public Base1
{
public:
    Inter2() { value = 2; }
    // int getValue() { return value; }
};

class Derived : public Inter1, public Inter2
{
public:
    void printData() { cout << "The value in Base class is: " << getValue() << endl; } // base will     be inherited through Inter2.
    // If you did class Derived : public Inter1, public Inter2 {}; base will be inherited through Inter1.
};

int main()
{
    Derived var;
    cout << "Hello";
    var.printData();

    return 0;
}

Virtual Base Class:

        In a long program with multiple inheritance, the diamond problem is very common ie you can inherit a base class from a number of parent classes, and thus ambiguity occurs. 

So, in order to avoid this you can make all the parent classes inherit the base class virtually. So, when some other class inherits the parents, the base class will be inherited only once.

#include <iostream>
using namespace std;
class Student
{
private:
    string name;

public:
    Student(string n = "") { name = n; }
    void setName(string n) { name = n; }
    string getName() { return name; }
    void display() { cout << "Name: " << name << endl; }
};

class Exams : virtual protected Student
{
private:
    float marks;

public:
    Exams(float m = 0) { marks = m; }
    void setMarks(float m) { marks = m; }
    float getMarks() { return marks; }
    void display() { cout << "Marks: " << marks << endl; }
};

class Sports : virtual protected Student
{
private:
    int score;

public:
    Sports(int m = 0) { score = m; }
    void setScore(int m) { score = m; }
    int getScore() { return score; }
    void display() { cout << "Score: " << score << endl; }
};

class Result : protected Exams, protected Sports
{
public:
    Result(string n = "", float r = 0, int s = 0) : Exams(r), Sports(s) { setName(n); }
    void display()
    {
        Student::display(); // if we didn't virtually inherited student class, here would be an error
        Exams::display();
        Sports::display();
    }
};

int main()
{
    Result r1("Developer", 91.8, 56);
    r1.display();
    return 0;
}


Constructors in a derived class:

  1. The constructor of the base class is executed before the derived class.
  2. The constructor of the virtual base class is invoked before the non-virtual base class.
  3. If there are multiple virtual base classes, they are invoked in the order of declaration.
  4. Any non-virtual base class is then constructed before the derived class constructor is executed.

// First Exams constructor will be called, then Sports constructor and then Result constructor
class Result : protected Exams, protected Sports
/*
Exams constructor is called
Sports Constructor is called
Result constructor is called
Name: Developer
Marks: 91.8
Score: 56
*/

Also:

// First Sports constructor will be called, then Exams constructor and then Result constructor
class Result : protected Sports, protected Exams
/*
Sports constructor is called
Exams Constructor is called
Result constructor is called
Name: Developer
Marks: 91.8
Score: 56
*/



13: Pointers: 

  1. To check the address of a container (a variable) you can use & symbol.
    int var = 5;
    cout << &var << endl; // 0x61fe14

  2. To create a pointer use * symbol and store address of a variable in it. The datatype of pointer must be the same as the datatype of variable that you want to store in the pointer. You can test if both has same address with following code.
    int var = 5;
    cout << &var << endl; // 0x61fe14
    int *ptr = &var; cout << ptr << endl; // 0x61fe14

  3. If you want to check the value at the address stored in the pointer, you can use de-referencing the pointer by just adding the * before the pointer name.
    int var = 5;
    int *ptr = &var;
    cout << "Value at ptr: " << *ptr << endl;

  4. You can change the value in the variable whose address is stored in the pointer by just using the pointer. To do this de-reference the pointer and then assign a new value to it.
    int var = 5;
    cout << "Old value at var: " << var << endl;
    int *ptr = &var;

    *ptr = 10;
    cout << "New value at var: " << var << endl;

  5. If you make a pointer and don't store address of a variable in it and de-reference it and store value in it, nothing will be stored anywhere because it does not know where to store the given value.

  6. If you take a pointer as a function parameter, you can pass the address of a variable as argument, it will work as if you passed a variable.
    int print(int *ptr)
    {
        return *ptr;
    }
    int main()
    {
        int num = 5;
        int *ptr = &num;

        cout << print(ptr) << endl   // 5
             << print(&num) << endl; // 5
    }

Void Pointer: 

        A void pointer is a pointer that can point to any datatype. However, it cannot be de-referenced simply. You have to first typecast it to the desired datatype.

#include <iostream>
using namespace std;
void print(void *ptr, char type)
{
    switch (type)
    {
    // first typecasting ptr to specific datatype the de-referencing it to print
    case 'i': cout << *((int *)ptr) << endl; break;
    case 'f': cout << *((float *)ptr) << endl; break;
    case 'd': cout << *((double *)ptr) << endl; break;
    case 'c': cout << *((char *)ptr) << endl; break;
    case 's': cout << *((string *)ptr) << endl; break;
    case 'b': cout << *((bool *)ptr) << endl; break;

    default:
        cout << "Invalid Input\n";
        break;
    }
}

int main(){
    int var1 = 5;
    print(&var1, 'i');

    float var2 = 5.56;
    print(&var2, 'f');
   
    double var3 = 5.56786778;
    print(&var3, 'd');
   
    char var4 = 'a';
    print(&var4, 'c');
   
    string var5 = "Hello";
    print(&var5, 's');
   
    bool var6 = true;
    print(&var6, 'b');
}


Pointers and Arrays:

int numbers[5] = {1, 2, 3, 4, 5};

// below line gives address of first element of array
cout << numbers << endl; // 0x61fe00

// we can test this by checking the address of first element of array
cout << &numbers[0] << endl; // 0x61fe00

// as number contains address of first element, we can print first element by de-referencing this
cout << *(numbers) << endl; // 1

// if we want to print out next number, we can do following
cout << *(numbers + 1) << endl; // 2

// we can also do this in for loop to print out whole array
for (int i = 0; i < sizeof(numbers) / sizeof(int); i++)
{
    cout << *(numbers + i) << ' ';
}
// 1 2 3 4 5

// we did this following way previously
for (int i = 0; i < sizeof(numbers) / sizeof(int); i++)
{
    cout << numbers[i] << ' ';
}
// 1 2 3 4 5


Returning multiple values from a function:

    You can return multiple values from a function by passing value by reference as argument and getting that in a pointer parameter and then changing the value of that pointer by de-referencing so that the variable in main, whose address is passed to the function also change.

#include <iostream>
using namespace std;

// without pointers functions
int getMaxNum(int arr[], int size)
{
    int max = arr[5];
    for (int i = 0; i < size; i++)
    {
        if (arr[i] > max)
        {
            max = arr[i];
        }
    }
    return max;
}

int getMinNum(int arr[], int size)
{
    int min = arr[5];
    for (int i = 0; i < size; i++)
    {
        if (arr[i] < min)
        {
            min = arr[i];
        }
    }
    return min;
}

// with pointers to return multiple values
void getMinMax(int arr[], int size, int *high, int *low)
{
    for (int i = 0; i < size; i++)
    {
        if (arr[i] > *high)
        {
            *high = arr[i];
        }
    }
    for (int i = 0; i < size; i++)
    {
        if (arr[i] < *low)
        {
            *low = arr[i];
        }
    }
}
// the values will be stored at the address of high and low pointers that has same address
as that of min and max variables in main

int main()
{
    int numbers[7] = {4, 2, 76, 34, -3, -43, 0};

    // without pointer
    cout << "Without pointers: " << endl;
    cout << "Min number: " << getMinNum(numbers, sizeof(numbers) / sizeof(int)) << endl;
    cout << "Max number: " << getMaxNum(numbers, sizeof(numbers) / sizeof(int)) << endl
         << endl;

    // with pointer
    cout << "With pointer: " << endl;
    int min = numbers[0], max = numbers[0];
    getMinMax(numbers, sizeof(numbers) / sizeof(int), &max, &min);
    cout << "Min number: " << min << endl;
    cout << "Max number: " << max << endl;

    return 0;
}


Passing Array to a function using pointer:

#include <iostream>
using namespace std;
// making a float pointer an accepting the address of 1st element of array
void toInches(float *x, int size)
{
    // iterating over all array by adding one to 1st element of array
    for (int i = 0; i < size; i++)
    {
        *(x + i) *= 2.54;
    }
}

int main()
{
    float array[5] = {1.34, 54.2, 33, 2.45, 32.56};
    cout << "Array in Centimeter: ";
    for (float element : array)
    {
        cout << element << ' ';
    }

    cout << "\nArray in Inches: ";
    // passing address of 1st element of array
    toInches(array, 5);
    for (float element : array)
    {
        cout << element << ' ';
    }

    return 0;
}



Const pointer and const pointing pointer: 

Const pointing pointer:        
        In it you will write const before datatype ie const int *ptr = &num1;. This makes the pointer not to change the value of variable whose address is stored in it but you can change the variable to which it is pointing to.

#include <iostream>
using namespace std;
int main()
{
    int num1 = 5;
    int num2 = 8;

    const int *ptr = &num1;
    *ptr = 6; // this gives an error because we are changing the value of const variable
   
    ptr = &num2; // but this works perfectly fine ie You can change the address stored in pointer
}

Const pointer:
        In it, you write const between pointer name and datatype* ie int *const ptr = &num1;. This make pointer itself constant ie you cannot change the address stored in the pointer.

#include <iostream>
using namespace std;
int main()
{
    int num1 = 5;
    int num2 = 8;

    int *const ptr = &num1;
    // int* const ptr = &num1;

    *ptr = 6; // this works perfectly fine ie you can change the value of variable

    ptr = &num2; // but this gives an error ie you cannot change the address to which pointer is pointing
}

Dynamic Pointers:

Dynamically created variables:

  1. Create a variable dynamicallydatatype *ptrName = new datatype(value)  
    • If you don't want to initialize it: datatype *ptrName = new datatype 
  2. Destroy dynamically allocated memorydelete ptrName 
#include <iostream>
using namespace std;
int main()
{
    int *ptr1 = new int(4); // same as (int a = 5; ptr = &a;) but we don't have to make variable
    cout << "ptr1: " << *ptr1 << endl; // 4
    delete ptr1;

    int *ptr2 = new int;
    *ptr2 = 8;
    cout << "ptr2: " << *ptr2 << endl; // 8
    delete ptr2;
   
    cout << "ptr1 after deleting: " << *ptr1 << endl; // 40574096
    cout << "ptr2 after deleting: " << *ptr2 << endl; // 40574096s

    return 0;
}

Dynamically created array: 

  1. Create an array dynamically: datatype *ptrArrName = new datatype[size]; ie use [ ] not ( )
  2. Destroy dynamically allocated memory: delete[] ptrArrName; 

#include <iostream>
using namespace std;
int main()
{
    int size;
    cout << "Enter the size of array: ";
    cin >> size;

    // allocating of memory
    int *arr = new int[size];

    // performing functions on our dynamically created array
    for (int i = 0; i < size; i++)
    {
        cout << "Enter value at index # " << i << ": ";
        cin >> *(arr + i);
    }
    for (int i = 0; i < size; i++)
    {
        cout << "Element at index # " << i << ": " << *(arr + i) << endl;
    }

    // de-allocation of memory
    delete[] arr;
    arr = NULL; // to make this pointer point to nothing
    return 0;
}

Dynamically created 2D Array:


#include <iostream>
using namespace std;
int main()
{
    int rows, cols;
    cout << "Enter the number of rows: ";
    cin >> rows;
    cout << "Enter the number of columns: ";
    cin >> cols;

    // allocation of memory to pointer pointing to rows array
    int **_2Darray = new int *[rows];
    // ** means pointer to pointer
    // *[] means each element of array is also pointer

    // allocation of memory to every row ie making every row an array of columns
    for (int i = 0; i < rows; i++)
    {
        _2Darray[i] = new int[cols];
    }

    // performing functions on array
    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < cols; j++)
        {
            cout << "Enter the value at row: " << i << " and col: " << j << ": ";
            cin >> _2Darray[i][j];
        }
    }
    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < cols; j++)
        {
            cout << _2Darray[i][j] << ' ';
        }
        cout << endl;
    }

    // destroying columns
    for (int i = 0; i < rows; i++)
    {
        delete[] _2Darray[i];
    }
    // destroying rows
    delete[] _2Darray;
    _2Darray = NULL;

    return 0;
}

Dynamically created objects:

#include <iostream>
using namespace std;
class Complex
{
private:
    float real, imaginary;

public:
    Complex(float r = 0, float i = 0) { real = r, imaginary = i; }
    void setData(float r, float i) { real = r, imaginary = i; }
    void display() { cout << "Complex number: " << real << " + " << imaginary << 'i' << endl; }
};

int main()
{
    Complex C1;
    Complex *ptrC1 = &C1;
    (*ptrC1).setData(2.3, 3.4); // In (*ptrC1), brackets are necessary bcz precedance of . is higher than *
    (*ptrC1).display();

    // OR

    Complex *ptrC2 = new Complex; // without initialization
    (*ptrC2).setData(3.2, 5.4);
    (*ptrC2).display();

    // OR
    Complex *ptrC3 = new Complex(2.7, 7.2); // with initialization
    (*ptrC3).display();

    // OR

    // Recomended
    Complex *ptrC4 = new Complex(12.7, 32.5);
    ptrC4->display(); // with -> you can remove both * and ()

    delete ptrC1;
    delete ptrC2;
    delete ptrC3;
    delete ptrC4;

    return 0;
}

Dynamically created array of objects: 
#include <iostream>
using namespace std;
class Complex
{
private:
    float real, imaginary;

public:
    Complex(float r = 0, float i = 0) { real = r, imaginary = i; }
    void setData(float r, float i) { real = r, imaginary = i; }
    void display() { cout << "Complex number: " << real << " + " << imaginary << 'i' << endl; }
};

int main()
{
    int size;
    cout << "Enter the size: ";
    cin >> size;
    Complex *ptrArray = new Complex[size];
    for (int i = 0; i < size; i++)
    {
        float x, y;
        cout << "Enter real value at index # " << i << ": ";
        cin >> x;
        cout << "Enter the imaginary value at index # " << i << ": ";
        cin >> y;
        ptrArray[i].setData(x, y);

    /*  OR

        ptrArray->setData(x, y);
        ptr++;
        but after this you have to minus size from ptrArray to make it point to first object again
    */
    }

    for (int i = 0; i < size; i++)
    {
        (ptrArray + i)->display();
    }

    delete[] ptrArray;
}

this pointer:
        this is a keyword which is a pointer that points to the local variable of a method within a class.
For example, if both constructor and private variables have the same name, you can still assign constructor variables to private class variables using this-> keyword so that there is no error to the compiler.

#include <iostream>
using namespace std;
class Complex
{
private:
    float real, imaginary;

public:
    Complex(float real = 0, float imaginary = 0)
    {
        this->real = real;
        this->imaginary = imaginary;
    }
    void setData(float real, float imaginary)
    {
        this->real = real;
        this->imaginary = imaginary;
    }
    void display() { cout << "Complex number: " << real << " + " << imaginary << 'i' << endl; }
};

int main()
{
    Complex c1(3.21, 5.32);
    c1.display();
}











Comments

Popular posts from this blog

88: Using switch statement Write a C program to input marks of five subjects Physics, Chemistry, Biology, Mathematics and Computer. Calculate percentage and grade according to following: // Percentage >= 90% : Grade A Percentage >= 80% : Grade B Percentage >= 70% : Grade C Percentage >= 60% : Grade D Percentage >= 40% : Grade E Percentage < 40% : Grade F

205: Book Catalog: Define a struct to represent a book with attributes like title, author, and publication year. Write a program to create a catalog of books by taking user input and display books published after a certain year.

15: Take input of age and name of 3 people by user and determine oldest and youngest among them with his age. -_-_-_-_-_-_-_-_-(line with spaces input concept)-_-_-_-_-_-_-_-_