Unit - 2 Oocp
Unit - 2 Oocp
Ans. A member function in a class is a function that operates on the instances (objects) of that class.
It is defined inside the class and has access to the data members of the class. Member functions can
manipulate the data members, providing functionality specific to the class.
To define a member function in C++, we declare it within the class definition and then implement it
either inside or outside the class. When implemented outside, the scope resolution operator (::) is
used to link the function to its class.
class MyClass {
public:
int data;
};
Ans. Nesting of member functions refers to calling one member function of a class from within
another member function of the same class. This allows for a more modular and organized code
structure, as one member function can perform part of the functionality while another handles a
different part.
#include <iostream>
class Calculator {
private:
int a, b;
public:
// Member function to input values
void inputValues() {
int add() {
return a + b;
void displayResult() {
cout << "The sum is: " << sum << endl;
};
int main() {
Calculator calc;
return 0;
Explanation:
• displayResult() calls add() from within its body to get the sum and then displays it.
This is an example of how member functions can interact by nesting one within another to create a
more structured flow
Q3. Explain private member function.
Ans. A private member function in a class is a function that can only be accessed or called from
within other member functions of the same class. It cannot be called directly from outside the class
or by any non-member functions or objects. Private member functions are typically used for internal
utility operations that should not be exposed to users of the class but are essential to the class’s
internal operations.
Key points:
• Access scope: Private member functions can only be accessed by other member functions of
the same class.
• Encapsulation: They help enforce encapsulation by hiding the internal workings of the class
from the outside world.
• Utility: They are often helper functions that assist public member functions but don’t need to
be directly accessible by objects of the class.
#include <iostream>
class Box {
private:
int volume() {
public:
length = l;
width = w;
height = h;
void displayVolume() {
}
};
int main() {
Box b;
b.setDimensions(5, 4, 3);
b.displayVolume();
return 0;
Explanation:
• The function volume() is declared as private, so it can only be called from within the class,
such as by the public function displayVolume().
• If you try to call b.volume() directly in the main() function, it will result in a compile-time
error because volume() is a private member of the class.
This structure allows the class to maintain control over its internal logic and hide unnecessary details
from the user, promoting better design and security in object-oriented programming.
Ans. In C++, memory allocation for objects occurs when an object is created. This memory is used to
store the object's data members, and the size of the allocated memory depends on the type and
number of data members the object contains. Memory can be allocated either on the stack (for local
objects) or the heap (for dynamically allocated objects), and this affects the object's lifetime and
scope.
o The object is destroyed automatically when the function exits or the block scope
ends.
class MyClass {
int data;
};
int main() {
MyClass obj;
}
Dynamic Memory Allocation (Heap):
• Objects can be dynamically allocated at runtime using the new operator, which allocates
memory on the heap.
• Dynamically allocated objects persist until explicitly deallocated using the delete operator.
• This gives the programmer more control over the object's lifetime, allowing the object to
persist even after the function that created it ends.
class MyClass {
int data;
};
int main() {
• Stack Memory: Memory for objects allocated on the stack is automatically managed and
limited in size. It's faster but has a short lifetime, limited to the scope of the function.
• Heap Memory: Memory for dynamically allocated objects (using new) is allocated on the
heap, which is larger but must be manually managed by the programmer (using delete).
• Memory size is determined by the types and number of data members (e.g., int, float, etc.).
• No memory is allocated for member functions, as they are shared among all instances of the
class.
class MyClass {
int a;
double b;
};
int main() {
MyClass obj;
}
Q5. Characterize static data members and static member functions.
Ans. In C++, both static data members and static member functions belong to the class rather than
any specific instance of the class. This means they are shared among all instances (objects) of the
class, and can be accessed without creating an object. Let's break down their characteristics:
• Shared by all objects: A static data member is shared among all instances of the class,
meaning there is only one copy of it for the entire class. All objects of the class can access
and modify this single shared variable.
• Class-level scope: Static data members exist at the class level, not at the object level. They
are declared inside the class but must be defined outside of the class (unless initialized in-
class in C++17 or later).
• Lifetime: The lifetime of a static data member extends for the entire duration of the program,
meaning it is created when the program starts and destroyed when the program ends.
• Access: Can be accessed using the class name (e.g., ClassName::staticMember) or through an
object, though the former is more common.
class MyClass {
public:
MyClass() {
count++;
};
int MyClass::count = 0;
int main() {
cout << "Number of objects: " << MyClass::count << endl; // Output: 2
return 0;
• Class-level functions: Static member functions can be called without creating an object of the
class. They are associated with the class itself, not with any particular object.
• Cannot access non-static members directly: Since static member functions are not tied to any
instance, they cannot access non-static data members or non-static member functions
directly. They can only access static data members and other static member functions.
• No implicit this pointer: Unlike non-static member functions, static member functions do not
have an implicit this pointer because they do not operate on specific instances.
class MyClass {
public:
MyClass() {
count++;
return count;
};
int MyClass::count = 0;
int main() {
cout << "Object count: " << MyClass::getCount() << endl; // Output: 2
return 0;
Ans. A constructor is a special member function in a class that is automatically called when an object
of that class is created. Its primary purpose is to initialize the object's data members and set up any
necessary conditions for the object to function correctly. Constructors allow the creation of objects
with an initial state, ensuring that the object is ready for use as soon as it is instantiated.
1. Same name as the class: A constructor has the same name as the class it belongs to.
2. No return type: Constructors do not have a return type, not even void.
Types of Constructors:
1. Default Constructor:
class MyClass {
public:
};
2. Parameterized Constructor:
class MyClass {
public:
int x;
x = val;
};
3. Copy Constructor:
• Used to create a new object as a copy of an existing object.It takes a reference to an object
of the same class as a parameter.
class MyClass {
public:
int x;
x = obj.x;
};
Uses of a Constructor:
1. Initialization: A constructor initializes data members when an object is created, ensuring that
the object starts in a valid state.
2. Setting up resources: Constructors can allocate resources (like memory, file handles, etc.)
that the object needs during its lifetime.
3. Encapsulation and abstraction: By using constructors, you can hide complex initialization
code from the user, allowing objects to be created simply and safely without exposing
unnecessary details.
Ans. In C++, there are several types of constructors that serve different purposes when creating and
initializing objects. These include:
1. Default Constructor
• A default constructor is a constructor that takes no arguments (or has default parameters)
and initializes objects with default values.
• Purpose: To initialize data members with default values when no specific values are provided.
class MyClass {
public:
int x;
x = 0;
};
int main() {
MyClass obj;
2. Parameterized Constructor
• A parameterized constructor is a constructor that takes one or more parameters to allow for
initializing an object with specific values provided by the user.
• Purpose: To initialize objects with custom values provided at the time of object creation.
class MyClass {
public:
int x;
x = val;
};
int main() {
MyClass obj(10
3. Copy Constructor
• A copy constructor is a special constructor that creates a new object as a copy of an existing
object. It takes a reference to an object of the same class as a parameter.
• If a copy constructor is not explicitly defined, the compiler provides a default copy
constructor that performs a shallow copy (bitwise copy of member values).
• Purpose: To create an object by copying the data members of another object, especially
useful when working with objects that manage resources like memory.
class MyClass {
public:
int x;
// Copy constructor
x = obj.x;
};
int main() {
MyClass obj1(5);
MyClass obj2 = obj1; // Copy constructor is called
4. Destructor
class MyClass {
public:
~MyClass() { // Destructor
};
5.onversion Constructor
• A conversion constructor is a constructor that takes a single argument of a different type and
converts that argument into an object of the class.
• Purpose: To allow implicit or explicit type conversions from one type to the class type.
class MyClass {
public:
int x;
// Conversion constructor
};
int main() {
}
Q8. Explain constructor overloading.
Ans. Constructor overloading in C++ refers to the ability to define multiple constructors in a class,
each having a different set of parameters. This allows objects to be initialized in various ways
depending on the needs of the user. Each overloaded constructor performs a similar task (object
initialization) but with different input, which provides flexibility in object creation.
1. Same name, different signatures: All constructors must have the same name as the class but
differ in the number or types of parameters.
2. Multiple ways of initialization: By defining multiple constructors, you give users the ability to
initialize an object in different ways (e.g., with no parameters, with one parameter, or with
multiple parameters).
#include <iostream>
class Rectangle {
private:
int length;
int width;
public:
// Default constructor
Rectangle() {
length = 1;
width = 1;
Rectangle(int l) {
length = l;
width = 1;
cout << "Parameterized constructor with one parameter called!" << endl;
Rectangle(int l, int w) {
length = l;
width = w;
cout << "Parameterized constructor with two parameters called!" << endl;
void displayArea() {
};
int main() {
return 0;
class Person {
private:
string name;
int age;
public:
// Default constructor
Person() {
name = "Unknown";
age = 0;
Person(string n) {
name = n;
age = 0;
Person(string n, int a) {
name = n;
age = a;
void displayInfo() {
cout << "Name: " << name << ", Age: " << age << endl;
}
};
int main() {
return 0;
Ans. A dynamic constructor in C++ is a constructor that dynamically allocates memory for data
members during object creation using dynamic memory allocation functions like new. This is useful
when the size of the data is not known at compile-time and needs to be determined at runtime.
In a dynamic constructor, memory for data members (typically arrays or objects) is allocated on the
heap, and the constructor manages this memory allocation.
1. Dynamic memory allocation: Uses new (or malloc in C-style) to allocate memory for data
members during object creation.
2. Memory management: The constructor is responsible for allocating memory, and the
destructor should deallocate it using delete to avoid memory leaks.
3. Flexible object size: Objects can have data members whose size or quantity is determined
dynamically based on runtime information.
1. Memory Allocation: Allocate memory dynamically for the data members using new.
2. Efficient memory usage: Since the memory is allocated on the heap, large objects don't
occupy space on the stack, preventing stack overflow in cases of large data sizes.
3. Dynamic object sizing: It supports dynamic sizing of arrays or other data structures within
the class, providing flexibility for managing varying data sizes.
Disadvantages:
2. Complexity: Managing dynamic memory can add complexity to the code and increase the
chances of errors such as memory leaks or invalid memory access.
Ans. In C++, a destructor is a special member function of a class that is automatically invoked when
an object of that class is destroyed (e.g., when it goes out of scope or is explicitly deleted). It is
primarily used to release resources that the object may have acquired during its lifetime, such as
memory, file handles, or network connections.
1. Same Name as the Class: The destructor has the same name as the class but is prefixed with
a tilde ~.
2. No Parameters: A destructor does not take any parameters and cannot be overloaded.
3. No Return Type: Destructors do not have a return type, not even void.
#include <iostream>
class Demo {
public:
Demo() {
~Demo() {
};
int main() {
return 0;
Output:
Constructor called!
Destructor called!
• Freeing Dynamic Memory: If you dynamically allocate memory in the constructor, the
destructor should free it to prevent memory leaks.
• Closing Files/Connections: A destructor can ensure that files or database connections are
properly closed when the object is destroyed.
Ans. In C++, while many operators can be overloaded, there are a few that cannot be overloaded.
These operators have specific functionality tied to the language itself, and C++ does not allow
overloading for them.
o Example: object.member.
o Example: (object.*pointer_to_member).
o This operator returns the size (in bytes) of a data type or object.
o Example: sizeof(int).
o This operator is used in runtime type identification (RTTI) to get information about
the type of an object.
o Example: typeid(object).
o Example: alignof(type).
o These are used for type casting in different contexts. C++ provides explicit cast
operators that cannot be overloaded.
o Example: dynamic_cast<Type*>(ptr).
o Although the standard new and delete operators can be overloaded, the placement
new and placement delete cannot.
class Number
private:
int x;
public:
Number(int p)
{
x = p;
x = -x;
void display()
cout<<"x = "<<x;
};
int main()
Number n(10);
-n;
n.display();
return 0;
Ans. Operator overloading in C++ allows you to redefine the behavior of operators for user-defined
types (like classes). However, there are several rules and guidelines you need to follow when
overloading operators.
• You cannot create new operators. Only the operators already defined in C++ can be
overloaded.
• The precedence and associativity of an operator cannot be altered through overloading. The
overloaded operator will follow the same precedence rules as the original operator.
• Unary operators (like -, !, ++, --) can be overloaded as either a member function with no
arguments or a non-member function with one argument.
• Binary operators (like +, -, *, /) take one parameter when overloaded as a member function
and two parameters when overloaded as a non-member function.
• Operators like assignment (=), subscript ([]), and compound assignment (+=, -=, etc.) should
return by reference to allow chaining and to prevent copying.
• It is recommended that the overloaded operator maintain its original intent. For example,
overloading the + operator should have a meaning related to addition.
10. Assignment, Subscript, Function Call, and Arrow Operators Must Be Members
• If one of the operands is a built-in type and the other is a user-defined type, the operator
function should be a non-member function to ensure symmetry.
• The assignment operator (=) should handle self-assignment and correctly manage deep
copies if the object manages resources like dynamic memory.
• When overloading binary operators like +, *, -, it’s often useful to ensure symmetry, meaning
both a + b and b + a should be valid if possible. This can often be achieved by overloading the
operator as a non-member function or providing both versions of the operator (for example,
int + MyClass and MyClass + int).
• You can overload both the prefix and postfix versions of ++ and --:
o Postfix form: obj++ (overload as operator++(int); the int is a dummy argument used
to differentiate it from the prefix version).
Ans. In C++, type conversion (also known as type casting) refers to the process of converting a value
from one data type to another. There are two main types of type conversion:
Implicit type conversion happens automatically by the compiler when the data types involved are
compatible. It is performed when:
• The conversion is safe, meaning no loss of data or precision occurs (e.g., converting from int
to float).
• It is part of an arithmetic expression, or when assigning values from one type to another.
int a = 10;
• Widening conversions (e.g., int to float, float to double) are safe and commonly performed
automatically.
• Narrowing conversions (e.g., double to int, long to short) might lead to a loss of precision,
and though they might still happen automatically, they could cause unexpected results.
Explicit type conversion, also known as type casting, requires the programmer to manually specify
the conversion. It is used when implicit conversion is not provided or is undesirable.
a) C-Style Casting
double pi = 3.14159;
b) Function-Style Casting
double pi = 3.14159;
Ans. In C++, you can define a class-to-basic type conversion by overloading a type conversion
operator, also known as a conversion operator. This allows an object of a class to be converted to a
basic data type (such as int, double, etc.).
In this example, we'll define a class Distance that holds distance in meters, and we'll provide a
conversion operator to convert an object of Distance to an int (which will return the distance in
meters).
#include <iostream>
class Distance {
private:
int meters;
public:
// Constructor
Distance(int m = 0) : meters(m) {}
};
int main() {
Distance d1(100);
d1.display();
return 0;
Important Points:
• The conversion operator does not have a return type (even though it returns a value), as its
return type is implied by the type it converts to.
• It’s good practice to mark the conversion operator as const to ensure it does not modify the
object.
• If the conversion should be explicit (i.e., not automatic but manual), you can use the explicit
keyword to prevent implicit conversions and require the use of static_cast.