207: Classes and OOP
- Important points
- Class Syntax
- Define the class function outside the class
- Practice program 1
- Static data members and static functions
- Array of objects
- Passing objects as function arguments
- Friend function
- Constructors
- Constant keyword and const member function
- Operator overloading
- Inheritance
- Pointers
1. Important points:
- Classes don't take any memory.
- Class always ends with };
- Memory is only allocated when an object is created.
- unsigned int count; unsigned int means its value will always be non-negative.
- 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.
- By default everything in the class is private.
- 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.
- Public functions are called manners or behaviors.
- 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.
- 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.
- When no copy constructor is found, the compiler supplies its own copy constructor.
- 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.
- 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:
3. Define the class function outside the class:
4. Practice program 1:
5: Static Data member and static functions:
- When a data member is declared static, only one copy of the data is maintained for all class objects.
- You have to declare it inside the class and define it outside the class.
- 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 objects, 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.
6: Array of objects:
7. Passing objects as function arguments:
8: Friend function:
- A friend function is simply a user-defined function that can access the private and protected data of a class.
- It is not in the scope of the class i.e. cannot be called from an object.
- Usually contains objects as arguments.
- Can be declared as friend in either public or private section of class.
- 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.
- 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).
- You can declare a function and then define it later outside the class to remove the errors like this class is not defined yet.
9: Constructors:
- Constructor is a special member function having the same name as the class.
- It is automatically invoked when an object is created and it initializes the object.
- It should be declared in the public section of the class.
- They cannot return value as they don't have a return type not even void.
- A constructor that takes no arguments is known as a default constructor.
- It can have default arguments like Complex ::Complex(int x, int y){real = x; imaginary = y;}. Such a constructor is called the parameterized constructor.
- We cannot refer to their address.
- 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
- Implicit constructor
- Explicit constructor
- Copy constructor creates a new object and initializes it by copying already existing object to it.
- If you don't make user user-defined copy constructor, the compiler will supply its own copy constructor.
- There are two methods of calling the copy constructor:
- Complex num2(num1);
- Complex num3 = num1;
- You should always initialize values in the same sequence with which the variables are declared while declaring class data members.
- Complex(int x, int y) : real(x), imaginary(y){cout << "Complex number: " << real << " + " << imaginary << 'i' << endl;}
- 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;}
- 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;}
- 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;}
- 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;}
- 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:
- 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; - 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); // syntaxExample:#include <iostream>using namespace std;void print(const int &x){// x = 6; This will give compile time errorcout << "Number: " << x << endl;}int main(){int num = 5;print(num);return 0; } - 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(); }; - 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; // syntaxExample:#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 errorcout << "Complex number: " << real << " + " << imaginary << 'i' << endl;}int main(){Complex num1(3);num1.print();return 0;} - 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:
- Scope operator ==> ::
- Size of operator ==> sizeof()
- member selector ==> .
- member pointer selector ==> *
- ternary operator ==> { ? : }
| Operators that can be overloaded | Examples |
|---|---|
| Binary Arithmetic | +, -, *, /, % |
| Unary Arithmetic | +, -, ++, — |
| Assignment | =, +=,*=, /=,-=, %= |
| Bitwise | & , | , << , >> , ~ , ^ |
| De-referencing | (->) |
| Dynamic memory allocation, De-allocation | New, delete |
| Subscript | [ ] |
| Function call | () |
| Logical | &, | |, ! |
| Relational | >, < , = =, <=, >= |
12: Inheritance:
In C++, inheritance is a process in which one object acquires all the properties and behaviors of its parent object automatically.
Advantage:
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:
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.
- In C++, the default mode of visibility is private.
- The private members of the base class are never inherited.
- 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.
- 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.

Where 'A' is the base class, and 'B' is the derived class.
Example 1:
Example 2:
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 visibility | Derived class visibility | ||
|---|---|---|---|
| Public | Private | Protected | |
| Private members | Not Inherited | Not Inherited | Not Inherited |
| Protected members | Protected | Private | Protected |
| Public members | Public | Private | Protected |
- 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:
- Virtual: You use 'virtual' keyword with the function in the base class that is to be overridden in the derived class
- Override: You use 'override' keyword with the function that is being overridden in the derived class.
- This shows an error during compile-time when the names of virtual and override functions are not same.
- 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"; }};
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.
Solution:
This can easily be solved by using the scope resolution operator ::
If derived class also has a function with same name, there will be no ambiguity because compiler will run the function of derived class.
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.
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.
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.
Constructors in a derived class:
- The constructor of the base class is executed before the derived class.
- The constructor of the virtual base class is invoked before the non-virtual base class.
- If there are multiple virtual base classes, they are invoked in the order of declaration.
- Any non-virtual base class is then constructed before the derived class constructor is executed.
Also:
13: Pointers:
- To check the address of a container (a variable) you can use & symbol.int var = 5;cout << &var << endl; // 0x61fe14
- 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; // 0x61fe14int *ptr = &var; cout << ptr << endl; // 0x61fe14
- 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;
- 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;
- 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.
- 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 = #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.
Pointers and Arrays:
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.
Passing Array to a function using pointer:
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.
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.
Dynamic Pointers:
Dynamically created variables:
- Create a variable dynamically: datatype *ptrName = new datatype(value)
- If you don't want to initialize it: datatype *ptrName = new datatype
- Destroy dynamically allocated memory: delete ptrName
Dynamically created array:
- Create an array dynamically: datatype *ptrArrName = new datatype[size]; ie use [ ] not ( )
- Destroy dynamically allocated memory: delete[] ptrArrName;
Dynamically created 2D Array:

Comments
Post a Comment