Sunteți pe pagina 1din 11

C++

1 : Reference variables :
References vs Pointers
Both references and pointers can be used to change local variables of one function inside another
function. Both of them can also be used to save copying of big objects when passed as arguments
to functions or returned from functions, to get efficiency gain.
Despite above similarities, there are following differences between references and pointers.
References are less powerful than pointers
1) Once a reference is created, it cannot be later made to reference another object; it cannot be
reseted. This is often done with pointers.
2) References cannot be NULL. Pointers are often made NULL to indicate that they are not
pointing to any valid thing. Although a reference variable can refer to a pointer variable which
points to Null.
3) A reference must be initialized when declared. There is no such restriction with pointers.
References are safer and easier to use:
1) Safer: Since references must be initialized, wild references like wild pointers are unlikely to
exist. It is still possible to have references that dont refer to a valid location.
2) Easier to use: References dont need dereferencing operator (*) to access the value. They can
be used like normal variables. & operator is needed only at the time of declaration. Also,
members of an object reference can be accessed with dot operator (.), unlike pointers where
arrow operator (->) is needed to access members.
In C++, variables are passed by reference due to following reasons:
1) To modify local variables of the caller function.
2) For passing large sized arguments. ( only valid for structure and class variable)
3)
4) To achieve Run Time Polymorphism in a function
2 : Default Argument:
An argument value that is specified at the time of function prototype or declaration is called
Default argument. This value is automatically passed to a function when no explicit argument is
specified in function call. When default argument are passed we have to follow the rules defining
values from right to left.
3 : Inline Function : Inline means during compile time.
C++ provides an inline functions to ( Main Advantage) 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.
Note : C++ compiler cannot perform if inlining if function is virtual (virtual means at runtime).
Syntax :
inline return-type function-name(parameters)
{
// function code
}

Inlining is only a request to the compiler, not a command. Compiler can ignore the request for
inlining. Compiler may not perform inlining in such circumstances like:
1. If a function contains a loop.
2. If a function contains a static variable.
3. If a function contains recursive call.
4. If a function contains switch or goto statement.
5. If a return type is other than void and return type does not exist in the function body.
Disadvantages :
1. Inlined function consumes additional registers, so if after function inlining variable numbers
increase drastically then it would surely cause an overhead on register utilization.
2. If u use too many inline functions then the size of the binary executable file will be large.
Inline function and classes:
1. It is also possible to define the inline function inside the class.
2. All the functions defined int class are implicitly inlined.
3. If you need to explicitly declare inline function in the class then just declare the function inside
the class and define it outside the class using inline keyword.
Bad programming Example :
class S
{
public:
inline inline* int square(int s) // redundant use of inline
{
// this function is automatically inline // function body
}
}; * implicitly added by compiler, thats the reason it will display redundant use of inline,
Good programming Example :
class S
{
public:
int square(int s); // declare the function
};
inline int S::square(int s) // use inline prefix
{
// Function Body
}
Summary :
In general function which performs input output (I/O) operation shouldnt be defined as inline
because it spends a considerable amount of time.
4. new and delete :
malloc() v/s new :
1. new is an operator, while malloc is a function.
2. new calls constructor, while malloc does not. All primitive data types can be initialized with new.
3. new returns exact data type, while malloc return void * i.e. , we need to typecast.
4. new never returns NULL, but will always throw an error on failure.
5. Memory for new comes from free store, while for malloc() it comes from heap.
6. new always returns pointers to distinct object i.e. address of 2 objects are different.

free() v/s delete :


delete is used to release the memory allocated by new or for a NULL pointer, while free() is used
to release the memory allocated by malloc() or for a NULL pointer.
5. Class and object :
Structure v/s Class :
1. Members of a class are private by default, while it is public in case of structure.
2. Class supports inheritance, while structure does not.
3. When deriving a struct from a class/struct, default access-specifier for a base class/struct is
public. And when deriving a class, default access specifier is private.
Can a C++ class have an object of self type ?
A class declaration can contain :
1. Static object of self type, as static variables do not contribute to the size of the class so no
problem in calculating the size of the class.
class Test {
static Test self; // works fine
/* other stuff in class*/
};
2. It can also have pointer to self type, as all pointers have fixed size irrespective of the data type
they are pointing to.
class Test {
Test * self; //works fine
/* other stuff in class*/
};
But it cannot have a non-static object of self type.
class Test {
Test self; // Compilation Error.
/* other stuff in class*/
};
Why is the size of an empty class not zero in C++?
The reason the size is non-zero is "To ensure that the addresses of two different objects will be
different." And the size can be 1 because alignment doesn't matter here, as there is nothing to
actually look at and to avoid division by 0 as pointer arithmetic involves dividing by sizeof(T).
class Empty { };
class Derived: Empty { int a; };
int main()
{
cout << sizeof(Derived); // Answer is 4 bytes.
return 0;
}
Reason : Rule says that an empty class need not to be represented by a separate byte.

6. Static Members :
Static member functions facts :
1. Static member functions do not have this pointer.
class Test {
static Test * fun() {
return this; // compiler error
}};
2. Static member function cannot be virtual.
3. Member function name with the same name and parameter type cannot be overloaded if either
of them is declared as static.
class Test {
static void fun() {}
void fun() {} // compiler error
};
4. Static member function cannot be declared as const, volatile or const volatile.
class Test {
static void fun() const // compiler error
};
5. Static member functions can be called without any object (with class name).
Static data member :
7. this pointer :
1. The this pointer is passed as a hidden argument to all non-static member functions calls and is
available as a local variable within the body of all non-static functions.
2. It is a constant which holds the memory address of the current object.
Following are the situations where this pointer is used:
1) When local variables name is same as members name.
2) To return reference to the calling object.
/* Reference to the calling object can be returned */
Test& Test::func ()
{ // Some processing
return * this;
}
When a reference to a local object is returned, the returned reference can be used to chain
function calls on a single object.
Type of this pointer :
The type of this depends upon function declaration.
If the member function of a class X is declared const, the type of this is const X*.
If the member function is declared volatile, the type of this is volatile X*.
If the member function is declared const volatile, the type of this is const volatile X*.
delete 'this' :
Ideally delete operator should not be used with this pointer.
If used following points must be considered.
1) delete operator works only for objects allocated using operator new .
2) Once delete this is done, any member of the deleted object should not be accessed after
deletion.
void fun() { delete this;
/* Invalid: Undefined Behavior */ ------> cout<<x; }

8. Function Overloading :
It is a feature where two or more functions can have the same name but different parameters.
It can be considered as an example of polymorphism.
Functions that cannot be overloaded :
Following function declarations cannot be overloaded :
1) Function declarations that differ only in the return type.
2) Member function declarations with the same name and the name parameter-type-list cannot
be overloaded if any of them is a static member function declaration.
3) Parameter declarations that differ only in a pointer * versus an array [] are equivalent. Only
the second and subsequent array dimensions are significant in parameter types.
int fun(int *ptr);
int fun(int ptr[]); // re-declaration of fun(int *ptr)
4)Two parameter declarations that differ only in their default arguments are equivalent.
int f ( int x, int y);
int f ( int x, int y = 10); // Both are same
5) Parameter declarations that differ only in the presence or absence of const and/or volatile are
equivalent. C++ allows functions to be overloaded on the basis of const-ness of parameters only if
the const parameter is a reference or a pointer.
6) Parameter declarations that differ only in that one is a function type and the other is a pointer
to the same function type are equivalent.
void h(int ());
void h(int (*)()); // re-declaration of h(int())
Note :
C++ allows member methods to be overloaded on the basis of const type. Overloading on the
basis of const type can be useful when a function return reference or pointer. We can make one
function const, that returns a const reference or const pointer, other non-const function that
returns non-const reference or pointer.
Can main() be overloaded?
1) To overload a main function it is necessary to use class and declare main as a member function.
2) main is not a keyword, hence it can be used as a variable name.
Does overloading work with Inheritance?
Overloading doesnt work for derived class in C++. There is no overload resolution between Base
and Derived. In C++, there is no overloading across scopes.
9. Constructor and Destructor :
Constructor :
1. It is a special member function enables an object to initialize itself.
2. This is known as automatic initialisation.
3. It is invoked only when object of its associated class is created.
4. It does not have a return type not even void.
5. Its name is same as that of the name of the class.
6. It is called only once for initialising the object.
7. It can be overloaded.
8. There can be constructor inside a constructor i.e. , nested constructor.
8. There can be more than one constructor in a class (constructor overloading), the only constraint
is that they all must have the different parameters, i.e. , it can be overloaded by changing the
number/ type of parameters.

There are 3 types of constructors :


1. Default constructor. (No parameter)
2. Parameterized constructor. (receives values on creation of object)
3. Copy constructor. // Most Important
Copy Constructor :
1. A copy constructor used to initialize an object using another object (const or non-const or
volatile) of same class.
Prototype : ClassName (const/volatile/(optional) ClassName & old_obj);
2. It is parameterized constructor having reference type constructor.
3. It is having parameter of type class.
4. this constructor receives another object in order to initialize current object.
When is copy constructor CAN (not always) called?
1. When the object of the class is returned by value.
2. When the object of the class is passed by value as an argument.
3. When an object is constructed based on the another object of same class.
4. When a compiler generates a temporary object.
Copy Constructor v/s Overloaded assignment operator :
MyClass t1, t2;
MyClass t3 = t1; // ----> Copy Constructor (1)
t2 = t1;
// -----> Overloaded Assignment operator (2)
(1) Copy constructor is called when a new object is created from an existing object, as a copy of
the existing object.
(2) Assignment operator is called when an already initialized object(old object) is assigned a new
value from another existing object. It is a member to member copy (shallow copy).
Shallow copy :
It only copies address of the original data member; this means they both share the same chunk of
memory.
Deep Copy :
Newly created object is initialized with the same data members as that of the parent object but
they both share the different memory spaces, deletion/modification of one object will not affect
the other object.
When is user defined copy constructor needed?
1. If we don't define the copy constructor, the C++ compiler creates a default copy constructor for
each class which does a member-wise copy between objects.
2. Don't write copy constructor if shallow copies are ok. If an object has no pointers or any run
time
allocation
of
resources,
a
shallow
copy
is
sufficient.
3. We need to define our own copy constructor only if an object has pointers or any runtime
allocation of resources like file handling, network connection..etc.
Why argument to a copy constructor must be passed as a reference?
1. A copy constructor is called when object is passed by value.
2. Copy constructor in itself is a function. So passing an argument by value in copy constructor, a
call to copy constructor would be made to call copy constructor which becomes a nonterminating chain of calls, i.e. it will get stuck in recursion. Therefore compiler doesn't allow
parameter to be pass by value.

Can we make a copy constructor private ?


Yes, a copy constructor can be made private. When we make a copy constructor private in a class,
objects of that class become non-copyable. This is particularly useful when our class has pointers
or dynamically allocated resources. In such situations, we can either write our own copy
constructor or make a private copy constructor so that users get compiler errors rather than
surprises at run time.
Why argument to a copy constructor should be const?
One reason for passing const reference is, we should use const in C++ wherever possible so that
objects are not accidentally modified.
Does compiler create default constructor when we write our own?
In C++, compiler by default creates default constructor for every class. But, if we define our own
constructor, compiler doesnt create the default constructor.
Functions that compiler implements for us if we don't define one?
1. Default constructor.
2. copy constructor.
3. Assignment operator.
4. Destructor.
5. * this pointer (holds the reference of current object).

Initialization of data members :


In C++, class variables are initialized in the same order as they appear in the class declaration.
Initializer List in C++ :
Initializer List is used to initialize data members of a class. The list of members to be initialized is
indicated with constructor as a comma separated list followed by a colon.
Ex: Point(int i = 0, int j = 0):x(i), y(j) {}
/* Above use of Initializer list is optional as constructor can also be written as:
Point(int i = 0, int j = 0) {
x = i;
y = j;
} */
So when to use it ?
1) For initialization of non-static const data members.
2) For initialization of reference members.
3) For initialization of member objects which do not have default constructor.
4) For initialization of base class members.
5) When constructors parameter name is same as data member or use *this pointer instead of
initializer list.
6) For Performance reasons.
Constant Member Function :
They are not allowed to change the value of data members.
Modifier :
It is a modifying function which changes the value of data function.
Accessor :
A member function which does not change the value of a data members. These functions
performs constant operations and are declared as constant.

Syntax :
return_type func_name ([parameters]) const
{ // statements ....}
When does compiler create default and copy constructors ?
1) Compiler creates a default constructor if we dont define our own constructor
2) Compiler created default constructor has empty body.
3) Compiler also creates a copy constructor if we dont write our own copy constructor.
4) Unlike default constructor, body of compiler created copy constructor is not empty, it copies all
data members of passed object to the object which is being created.
5) Compiler doesnt create a default constructor if we write any constructor even if it is copy
constructor.
6) Compiler creates a copy constructor if we dont write our own. Compiler creates it even if we
have written other constructors in class.
Destructors :
1) A destructor de-allocates the resources allocated by the constructor.
2) It is a member function whose name is same as that of the class name.
3) A destructor name is preceded by (~) tilde symbol.
4) It never takes any argument nor it returns any value.
5) It is invoked implicitly when the program is terminated to clean up storage.
Syntax : ~ destructor_name(){ .... }
Private Destructor :
When a class has private destructor, only dynamic objects of that class can be created.
What is the use of private destructor?
Whenever we want to control destruction of objects of a class, we make the destructor private.
For dynamically created objects, it may happen that you pass a pointer to the object to a function
and the function deletes the object. If the object is referred after the function call, the reference
will become dangling.
Copy elision or Copy omission :
Copy elision (or Copy omission) is a compiler optimization technique that avoids unnecessary
copying of objects.
10. Inheritance :
1) The mechanism of deriving a new class from a old one is called inheritance.
2) Old class is referred is as Base class and new is called as Derived class.
3) A class can inherit properties form more than class / level.
Advantages of inheritance :
1) Reusability : Allows to use content of one class inside other class.
2) Extensibility : Allows us to extend functionality of existing class without modifying it.
Syntax :
class derived-class-name : visibility-mode base-class-name
{
// members of derived class
}
: indicates that derived class is derived from the base class

Visibility Mode :
1) It can be either private or public and is optional, default is private.
2) It defines visibility or accessibility of base class member within derived class.
Private visibility mode :
1) When the visibility mode is private, public members of the base class becomes private members
of the derived class.
2) The public members of the base class are accessible within derived class by using public and
protected member functions of base class.
Public visibility mode :
1) When the visibility mode is public, public members of the base class becomes the public
members of derived class.
2) They are accessible to the derived class objects.
Note :
1) Private members are accessed within the class.
2) Protected members are accessible within class & immediately derived class.
What all is inherited from Base class ?
1) Every data member defined in the parent class (although such members may not (depends on
visibility mode) always be accessible in derived class)
2) Every ordinary member function of the parent class (although such members may not (depends
on visibility mode) always be accessible in derived class)
3) The same initial data layout as the base class.
Following are the things which a derived class doesnt inherits from its Base:
1) The base classs constructors and destructor.
2) The base classs friends.
Constructors in Derived class (Mastering C++ --> 516-523):
1) The derived class need not have a constructor as long as the base class has no argument
constructor.
2) If the base class is having the constructors with arguments then it is mandatory for the derived
class to have a constructor and pass the argument to the base class constructor.
3) In inheritance object of derived class are usually created instead of base class.
4) When an object of a derived class is created, constructor of base class is executed first and then
the constructor of a derived class.
5) The compiler looks for no-argument constructor in the base class.
Destructors in inheritance :
1) Invoking of a constructors are from top to bottom while of destructors it is from bottom to top.
2) The Destructor that class whose constructor was executed last while building the object of the
derived class will be executed first.
Operator Overloading (Polymorphism) :
1) It is a process of giving special meaning to the existing operator.
2) All the operators can be overloaded except :
-- Class member access operator (.,.*)
-- Scope resolution operator ( :: )
-- Sizeof operator (sizeof)
-- Conditional operator ( ? :)

Syntax :
return_type operator operator_symbol ([parameter]) {// statements}
Rules to overload an operator:
1) Only existing operators can be overloaded.
2) We cannot change the basic meaning of the operator.
3) New operators cannot be created.
4) Operators must have at least one operand of user defined type.
Why can't I overload dot, ::, sizeof, etc ? (By Bjarne Stroustrup)
Most operators can be overloaded by a programmer. The exceptions are
. (dot) :: ?: sizeof
There is no fundamental reason to disallow overloading of ?:. I just didn't see the need to
introduce the special case of overloading a ternary operator. Note that a function overloading
expr1?expr2:expr3 would not be able to guarantee that only one of expr2 and expr3 was executed.
Sizeof cannot be overloaded because built-in operations, such as incrementing a pointer into an
array implicitly depends on it. Consider:
X a[10];
X* p = &a[3];
X* q = &a[3];
p++;
// p points to a[4]
// thus the integer value of p must be
// sizeof(X) larger than the integer value of q
Thus, sizeof(X) could not be given a new and different meaning by the programmer without
violating basic language rules.
In N::m neither N nor m are expressions with values; N and m are names known to the compiler
and :: performs a (compile time) scope resolution rather than an expression evaluation. One could
imagine allowing overloading of x::y where x is an object rather than a namespace or a class, but
that would - contrary to first appearances - involve introducing new syntax (to allow expr::expr). It
is not obvious what benefits such a complication would bring.
Operator . (dot) could in principle be overloaded using the same technique as used for ->.
However, doing so can lead to questions about whether an operation is meant for the object
overloading . or an object referred to by . For example:
class Y {
public:
void f();
// ...
};
class X { // assume that you can overload .
Y* p;
Y& operator.() { return *p; }
void f();
// ...
};
void g(X& x)
{
x.f();
}

// X::f or Y::f or error?

Can I define my own operators?


Sorry, no. The possibility has been considered several times, but each time I/we decided that the
likely problems outweighed the likely benefits.
It's not a language-technical problem. Even when I first considered it in 1983, I knew how it could
be implemented. However, my experience has been that when we go beyond the most trivial
examples people seem to have subtlety different opinions of "the obvious" meaning of uses of an
operator. A classic example is a**b**c. Assume that ** has been made to mean exponentiation.
Now should a**b**c mean (a**b)**c or a**(b**c)? I thought the answer was obvious and my
friends agreed - and then we found that we didn't agree on which resolution was the obvious one.
My conjecture is that such problems would lead to subtle bugs.

S-ar putea să vă placă și