using namespace std; // what does this imply ? what is a namespace ? what is its use ?
A namespace is a declarative region that provides a scope to the identifiers (the names of types, functions, variables, etc) inside it. Namespaces are used to organise code into logical groups and to prevent name collisions that can occur especially when your code base includes multiple libraries.
The statement above simply says that we are using software components from the C++ standard library, such as when you are using cout, it is actually std::cout .
Some functions are of quite small size, but quite frequently called. C++ provides an inline functions to reduce the function call overhead. Inline function is a function that is expanded in line when it is called. When the inline function is called whole code of the inline function gets inserted or substituted at the point of inline function call. This substitution is performed by the C++ compiler at compile time . Inline function may increase efficiency if it is small. Know more here
For a function to be inline, it can't contain a loop, static variables, switch or goto statement. Also, an inline function should not be recursive and if its return type is other than void then, return statement should be present in function body. If the function definition of a member function of a class is written inside the class itself, then that function is implicitly inline.
It is nothing but a different name (alias) for the same memory location . Eg.
int a=33;
int &b= a; /* Here, b is a reference for variable a DON'T CONFUSE THIS WITH POINTERS*/
cout << b; // output :- 33
(A) Using pointers (similar to C) - Actually call by address Eg.
void swap (int * a, int * b)
{
int t;
t=*a;
*a=*b;
*b=t;
}
In main(), we pass the addresses of variables to swap, swap(&c,&d);
(B) Using reference variables A reference is declared by putting "&" in front of the identifier in the function header . A reference is not a variable. It is just an alias of a variable. Eg.
void swap (int & a, int & b)
{
int t;
t=a;
a=b;
b=t;
}
In main(), just call normally, swap(c,d); (It will automatically pass by reference)
However, only the rightmost arguments can be omitted i.e. you can not provide the 1st and 3rd argument and omit the middle one
Eg.
float si (float principal, int r, int t=1 )
{
return t*r*principal;
}
In main(), call as si(33.00,2); It returns 66.00 taking default value of t as 1 because only 2 arguements are passed.
For function calls, binding means matching the call with the right function definition by the compiler. It takes place either at compile time or at runtime.
There are 2 types of binding :
i. Early Binding or static binding (Compile-time time polymorphism)
ii. Late Binding or dynamic binding (Run time polymorphism)
Functions with the same name but different signature (i.e. argument list or parameter list) are called overloaded functions. Overloaded functions are recognised by the compiler through the argument list in the call.
Example
void area(int a); // for calculating area of circle
void area(int a, int b); // for calculating area of rectangle using the same function
Just like an array name is the address of the first array element, a function name is a actually the starting address of the function code. For more, view here. Eg.
void fun(int a)
{
printf("Value of a is %d\n", a);
}
int main()
{
// fun_ptr is a pointer to function fun()
void (*fun_ptr)(int) = &fun; // Note the brackets
/* The above line is equivalent of following two
void (*fun_ptr)(int);
fun_ptr = &fun;
*/
// Invoking fun() using fun_ptr
(*fun_ptr)(10);
return 0;
}
(Only Useful in a menu-driven system, when all Functions have same signatures and prototypes)
char (*funPtr[3])(int) = {fun1, fun2,fun3};
int choice = 0;
while(choice != -1)
{
(*funPtr[choice])();
cin >> choice;
}
Class : It is a user-defined data type, which holds its own data members and member functions, which can be accessed and used by creating an instance of that class. Class acts as a blueprint for an object.
Object : An instance of a class, that has some properties (data members) and behaviours (member functions) associated with it.
When a class is defined, no memory is allocated but when it is instantiated (i.e. an object is created) memory is allocated.
There are 3 member access specifiers- public, private, protected All data members and methods declared by the public specifier are accessible from outside, and all declared by private are only accessible for methods.
If the method is defined inside the class body, it is automatically inlined. It may improve the performance (As it avoids calling of function) , but it is not good for information hiding, because the client of the object is able to see the implementation of its methods.
To define the method outside the class body , you have to use scope resolution operator ::
Private and protected data members can also be changed by friends of its class.
Both structures and classes have private, public and protected access specifiers. Default access specifier of classes is private, default for structure is public.
There are basically 5 types of member functions :-
Constructor (create an object with a legal initial value)
Access methods (getters and setters)
Service Methods (for services)
Utility Methods (private methods, which are called only by other methods of the same class)
Destructor (Destroying or releasing memory occupied by an object)
(A) There is a special method with the same name as the class called constructor . There is no return type (even not void) for this special method. Constructors can be overloaded .
(B) 3 types of constructor:-
Default - No arguement Used mostly for creating an array of objects
Parameterized - has some arguements
Copy Constructor - has an argument its own type, to copy a new object out of it.
It uses Call by reference, Otherwise the copy constructor call results in infinite recursion , because for call-by-value, a copy of the object passed to the copy constructor must be made, which results in the copy constructor being called recursively
Also, The object argument passed to the copy constructor must be constant. Otherwise it can not be applied on constant object. For more, view here
(C) When the user defines a parametrized Constructor, it hides the default constructor.
(D) If you want to have an array of objects that do not have a default constructor , the work-around is to have an array of pointers and initialize them using operator new . See examples here
(E) If copy constructor is not provided, compiler will provide a default copy constructor , which makes default memberwise copy, which can not deal with objects with pointer members (it will perform only shallow copy of pointers) . As in C++, objects are passed by value, by default , a copy constructor is generally required.
(A) Automatically called when an object leave scope to release all resources held by the object. The name of a destructor for a class is the tilde (~) character followed by the class name. Stack memory resources held by the object such as its compiler-created members are released automatically when the object leaves scope or explicitly deleted. A destructor is only needed to release resources which can not be automatically released, such as dynamically allocated memory (using "new") or network or database connection.
(B) Destructor is called when object goes out of scope .
(C) The order of calling of Constructor is just opposite to that of Destructors.
class Complex {
private:
int real, imag;
public:
Complex(int r = 0, int i =0) {real = r; imag = i;}
// This is automatically called when '+' is used with
// between two Complex objects
Complex operator + (Complex const &obj) {
Complex res;
res.real = real + obj.real;
res.imag = imag + obj.imag;
return res;
}
void print() { cout << real << " + i" << imag << endl; }
};
int main()
{
Complex c1(10, 5), c2(2, 4);
Complex c3 = c1 + c2; // An example call to "operator+"
c3.print();
}
class Complex {
private:
int real, imag;
public:
Complex(int r = 0, int i =0) {real = r; imag = i;}
void print() { cout << real << " + i" << imag << endl; }
// The global operator function is made friend of this class so
// that it can access private members
friend Complex operator + (Complex const &, Complex const &);
};
Complex operator + (Complex const &c1, Complex const &c2)
{
return Complex(c1.real + c2.real, c1.imag + c2.imag);
}
For operator overloading :
the function call operator can't have default arguements
All operators except = are accessed by derived class
Operators ( ), [ ], -> , = can be overloaded only as member function ( not as friend function)
In overloading Array index operator [] operator and -> operator, we need to return a reference
For unary operators, the parameter list is empty except postfix + +, - - Eg.
void operator ++ (); // prefix
void operator ++ (int); // postfix
ostream& operator << (ostream& out,Complex n){
out<<n.real;
if(n.img<0) out<<'-'<<'i';
else out<<'+'<<'i';
out<<(n.img<0? -(n.img): n.img);
return out;
}
Data hiding refers to hiding internal object details (data members). Data hiding ensures exclusive data access to class members and protects object integrity by preventing unintended or intended data alteration (or data modification). This is one of the important reason why OOP is preferred, nowadays.
Private members are implicitly visible ( enforce data hiding )
Data abstraction refers to providing only essential information about the data to the outside world, hiding the background details or implementation.
Consider a real life example of a man driving a car. The man only knows that pressing the accelerators will increase the speed of car or applying brakes will stop the car but he does not know about how on pressing accelerator the speed is actually increasing, he does not know about the inner mechanism of the car or the implementation of accelerator, brakes etc in the car.
Public members are explicitly visible ( enforce data abstraction )
List of members to be initialised is indicated with their constructor as a comma separated list followed by a colon. For more info, view here
Example
class Point {
private:
int x;
int y;
public:
Point(int i = 0, int j = 0):x(i), y(j) {} // initialisation using member initialisation list
};
The compiler supplies an implicit pointer to every non-static member function of a class, when it is called, this us called 'this' pointer. For more info, view here
this points to the calling object
this pointer is only an r-value, so its value can't be changed.
an object can be deleted (only if memory to it is dynamically allocated using new) by using following syntax :-
delete this;
class subclass_name : access_mode base_class_name
{
//body of subclass
};
Single Inheritance
Multilevel Inheritance :
Hierarchical Inheritance :
Multiple Inheritance :
Hybrid inheritance :
The diamond problem occurs when two super-classes of a class have a common base class ( multi-path inheritance ). For example, in the following diagram, the TA class gets two copies of all attributes of Person class, this causes ambiguities.
It can be resolved using any of the 2 methods :
5 Storage classes are there in C++
Automatic
Extern
Register
A function can have only 2 storage classes :
Out of these, static is possible only in member function of a class
class A {
public:
void display() {
cout<<"Base class";
}
};
class B:public A {
public:
void display() {
cout<<"Derived Class";
}
};
int main() {
B obj;
obj.display(); // Output : "Derived Class"
return 0;
}
A pure virtual function is declared in base class as virtual func() = 0;
It makes the base class, an abstract class. Abstract classes can't be instantiated i.e. we can't create objects of abstract classes but new classes can be derived using abstract classes.
Whenever a pure virtual function is present in a base class, it should be overridden in all the derived classes which should be concrete classes (have objects). If we don't do this in a derived class, it becomes an abstract class
Compiler silently adds a void pointer to an object of a class which contains Virtual functions
To accomplish late binding, the compiler creates a table called VTABLE for each class that contains Virtual functions and for the classes derived from it. The compiler places the addresses of virtual functions for that particular class in VTABLE .
If we don't redefine the function, it uses the address of the base class version in the derived class
When objects of the base class or derived class are created it secretly places a pointer, called the vpointer (VPTR) , which points to the VTABLE if its class.
When a function call is made through a base class pointer, the compiler inserts the code to fetch the VPTR and lookup function address in the VTABLE, thus calling the right function and causing Late Binding
VPTR must be initialised to point to the starting address of appropriate VTABLE (in constructor)
When an object of derived class is created, all the base class constructors are always called first, in constructor of derived class.(the reason is that only base class has access to its members, not the derived class. Moreover, base class members need to be initialised first as derived class members depend on base class)
Compiler calls the default constructor of base class if we don't explicitly call it in constructor of derived class.
When a virtual function is called within a constructor or destructor , always the member function of current class gets called (early binding) . In other words, virtual mechanism doesn't work inside a constructor or a destructor
Destructor can be virtual but a constructor can't be. Because once an object has been constructed, its VPTR is initialised, so the virtual function calls can take place
When type checking occurs at runtime (not at compile time), it is called Dynamic type checking .
It occurs through RTTI (runtime time information ) mechanism in C++
Used in dynamic casting of pointers
Eg.
Base *b = new Derived;
A derived class object can be assigned to a base class object (called Object Slicing) but the other way is not possible.
This is done at the cost of slicing of the additional data members of the derived class
Hence, we can call only functions of base class of a sliced object
It can be prevented by using pointers to class objects or by making the functions of base class as pure virtual (abstract class) as it will give compile error if you create a base class object
For example, view here
Actually an object contains only the data members. Methods do not belong to any specific object. They belong to the class. All objects share one copy of methods . When you use “sizeof” operator on a class or an object you will only get the total size of the data members.
Private members of a class are not inherited to a child class i.e. can't be used by member functions of child class but remember that they are included while calculating size of an object of child class
Size of an empty class is not 0. It is 1 byte generally, to ensure that 2 different objects will have different addresses
If a class is derived from a virtual base class, it has a pointer to that virtual base class, even when it is empty, resulting in a a size of at least 8 bytes always
Eg.
class radius
{
int num;
public:
void operator float () const {
float f = 3.14 x num;
return f;
}
};
From fundamental to class - Use conversion constructor (parametrised constructor)
We can prevent this type conversions most of the times, by using the keyword explicit before the constructor. Know more here
A friend class can access private and protected members of other class in which it is declared as friend. It is sometimes useful to allow a particular class to access private members of other class.
Example :
class Node {
private:
int key;
Node* next;
friend class LinkedList;
// Now class LinkedList can
// access private members of Node
};
Like friend class, a friend function can be given special grant to access private and protected members.
A friend function can be any of :
i. A method of another class
ii. A global function
It can be used in 2 situations :-
i. Operator overloading
ii. If some particular data and functions are required to be shared between 2 or more classes
Drawback of friend function is that it prevents the feature of data hiding upto some extent
Know more here
A factory method is a method which uses dynamic memory allocation to clone itself and return a pointer to the new copy . Suppose you have a abstract class Shape and a series of derived concrete classes such as Circle, Square, Rectangle, etc. A factory method of Circle looks like
Shape * clone()
{
return new Circle(*this); // calling copy constructor
}
public void modifyAndDisplay(Shape * obj)
{
Shape obj1 = obj. clone();
...
}
Templates are powerful features of C++ which allows you to write generic programs. In simple terms, you can create a single function or a class to work with different data types using templates.
2 types :
i. Function Template
ii. Class Template
Each instantiation of function template has its own copy of local static variables. View more here
template <class T>
T someFunction(T arg)
{
... .. ...
}
template <class T>
class className
{
... .. ...
public:
T var;
T someOperation(T arg);
... .. ...
};
className<dataType> classObject; // creation of object of a particular data type
// A generic sort function
template <class T>
void sort(T arr[], int size)
{
}
// A specialized version for char data type
template <>
void sort<char>(char arr[], int size)
{
// code to implement counting sort
}
Extraction operator ( cin >> ) ignores whitespaces like '\n', ' ', '\t', etc. So, while taking input with whitespaces , better use getline(cin,str)
If in a block a local variable of the same name as the global variable is declared, the local variable will suppress the global one from the declaration line onwards. So, to access the global variable from this block, use unary scope resolution operator "::" in front of the identifier. For more uses of scope resolution operator, view here
Scope resolution operator (::) is also used, for ambiguity resolution. Ambiguity can be occurred in using the multiple inheritance when a function with the same name occurs in more than one base class.
Labels are identifiers followed by a colon, eg., the case label “case 3: ” in “switch” structure. Labels are used in “switch” structure or “goto” statement to mark the location of a statement. A label (and only a label) declared inside a function is in scope everywhere in that function , in all nested blocks, before and after its own declaration.
Because block is the smallest unit in C++ , most variables/identifiers are of block scope . They are local variables declared in a block.
The principle of least privilege (PLP) is the idea that at any user, program, or process should have only the bare minimum privileges necessary to perform its function. In most cases it is achieved by using of qualifier const, or the private or protected access specifiers
By default, elements of an array are initialised to 0.
By default, arrays are passed by reference, similar to C , because name of an array is a constant pointer pointing to its first element (except when used with sizeof operator and & operator) .
A class can contain a static object of self type or a pointer to self type only. It can't have an object of own type as a data member.
Const keyword
Eg.
void strcpy(char *, const char *);
Eg.
const int size=4;