CSE202: OBJECT ORIENTED PROGRAMMING - UNIT I NOTES
Unit I: Concepts and Basics of C++ Programming
This unit introduces the fundamental syntax of C++ and the core concepts of Object-Oriented Programming (OOP), focusing on classes, objects, and basic input/output operations. Understanding these concepts is crucial for applying OOP principles (CO4) and building programming solutions (CO1, CO5, CO6).
1. C++ Program Structure and Basic I/O
A basic C++ program has a standard structure. Input and output operations are handled using streams, primarily cin
and cout
from the iostream
library.
1.1 Basic Program Structure
#include <iostream> // Include necessary header file
// Using a namespace to avoid prefixing standard library elements with std::
using namespace std;
int main() {
// Program logic goes here
cout << "Hello, World!" << endl; // Example output
return 0; // Indicate successful execution
}
#include <iostream>
: This preprocessor directive includes the standard input/output stream library, which provides functionalities likecin
andcout
.using namespace std;
: This line brings the standard namespacestd
into scope, allowing you to use names likecout
andendl
directly withoutstd::
. While convenient for small programs, in larger projects, it's often better to usestd::
explicitly or bring in specific names (e.g.,using std::cout;
).int main() { ... }
: This is the main function where program execution begins.return 0;
: Conventionally indicates that the program executed successfully.
1.2 Reading and Writing Data using cin
and cout
C++ uses streams for I/O. cout
is the standard output stream, and cin
is the standard input stream.
-
cout
(Standard Output Stream): Used to display output on the console.- The
<<
operator (insertion operator) is used withcout
to send data to the stream. endl
is a manipulator that inserts a newline character and flushes the output buffer.\n
also inserts a newline but may not flush the buffer immediately, which can be slightly more efficient in some cases.
#include <iostream> int main() { int age = 30; double price = 19.99; cout << "My age is: " << age << endl; cout << "The price is: $" << price << "\n"; // Using \n return 0; }
- The
-
cin
(Standard Input Stream): Used to read input from the console (keyboard).- The
>>
operator (extraction operator) is used withcin
to extract data from the stream and store it in a variable. cin
typically reads until whitespace (space, tab, newline) is encountered for fundamental data types.
#include <iostream> #include <string> // Required for std::string int main() { int number; string name; cout << "Enter a number: "; cin >> number; cout << "Enter your first name: "; cin >> name; // Reads until whitespace cout << "You entered: " << number << " and " << name << endl; // Reading a line with spaces // NOTE: If there's a leftover newline character in the buffer from previous cin >>, // getline might read it immediately. Use cin.ignore() to clear the buffer if needed. cin.ignore(); // Ignore the leftover newline character string full_name; cout << "Enter your full name: "; getline(cin, full_name); // Reads an entire line, including spaces cout << "Your full name is: " << full_name << endl; return 0; }
getline(cin, variable)
: A function from the<string>
header used to read an entire line of text from an input stream, including spaces, until a newline character is encountered.cin.ignore()
: A method to extract and discard characters from the input buffer. Useful after usingcin >>
before usinggetline
to consume the leftover newline.
- The
2. Introduction to Object-Oriented Programming (OOP) in C++
OOP is a programming paradigm that organizes software design around data, or objects, rather than functions and logic. It aims to model real-world entities and their interactions.
2.1 Differences between Procedural and Object-Oriented Programming Paradigms
Feature | Procedural Programming | Object-Oriented Programming |
---|---|---|
Focus | Functions/Procedures, logic, sequence of steps | Data, Objects, classes |
Structure | Programs divided into functions. Data is separate or global. | Programs organized into classes and objects. Data and functions are bundled. |
Data Handling | Data is often global or passed between functions. Data can be accessed by multiple functions. | Data is hidden (encapsulated) within objects and accessed only through member functions. |
Abstraction | Limited abstraction; focuses on step-by-step implementation. | High abstraction; hides complexity through objects and classes. |
Reusability | Code reuse is achieved through functions, but potentially limited by data dependencies. | Achieved through classes, inheritance, and polymorphism. |
Maintainability | Can be difficult to maintain as programs grow; changes in data structures affect many functions. | Easier to maintain; changes within a class are localized. |
Adding New Data/Features | Requires modifying existing functions and possibly data structures. | Easier to add new classes or extend existing ones without modifying core logic. |
Examples | C, Pascal, Fortran | C++, Java, Python, C# |
OOP principles (Encapsulation, Abstraction, Inheritance, Polymorphism) provide benefits like improved modularity, reusability (CO2), flexibility, and maintainability, helping in building robust software applications (CO6).
3. Classes and Objects
The foundation of OOP in C++ is the class.
- Class: A blueprint or template for creating objects. It defines the structure (data members) and behavior (member functions) that objects of that class will have. It's a user-defined data type.
- Object: An instance of a class. It is a concrete entity created based on the class blueprint. Each object has its own set of data members (state) and can perform the actions defined by the class's member functions (behavior).
3.1 Creating Classes
A class is defined using the class
keyword, followed by the class name and a block containing its members.
class ClassName {
private:
// Private data members (attributes) - accessible only within the class
dataType privateMember1;
dataType privateMember2;
public:
// Public data members or member functions (methods) - accessible from outside the class
dataType publicMember;
// Public member functions (methods)
returnType publicMethod1(parameters);
returnType publicMethod2(parameters);
private: // Can have multiple access specifiers
// More private members
}; // Don't forget the semicolon!
- Access Specifiers:
public
,private
, andprotected
control the visibility and accessibility of class members.public
: Members are accessible from anywhere, inside or outside the class.private
: Members are accessible only from within the class itself. This is key for encapsulation, hiding the internal implementation details.protected
: (Will be covered in detail later, related to inheritance) Members are accessible within the class and by derived classes.
3.2 Class Objects
Once a class is defined, you can create objects (instances) of that class. Creating an object is also called instantiation.
ClassName objectName; // Creates an object named objectName of type ClassName
// Example:
class Dog {
public:
string breed;
int age;
void bark() {
cout << "Woof!" << endl;
}
};
int main() {
Dog myDog; // Create an object of the Dog class
Dog yourDog; // Create another object
// ... access members ...
return 0;
}
3.3 Accessing Class Members
Members of an object are accessed using the dot operator (.
).
- You can only access
public
members directly using the dot operator from outside the class. private
andprotected
members can only be accessed by member functions of the same class (or derived classes forprotected
).
class Dog {
public:
string breed; // public data member
int age; // public data member
void bark() { // public member function
cout << breed << " says Woof!" << endl;
}
private:
string name; // private data member
public:
// Public method to set the private name (setter)
void setName(string dogName) {
name = dogName; // Accessible because it's inside the class
}
// Public method to get the private name (getter)
string getName() {
return name; // Accessible because it's inside the class
}
};
int main() {
Dog myDog;
// Accessing public members directly
myDog.breed = "Golden Retriever";
myDog.age = 5;
myDog.bark(); // Calling public member function
// Accessing private members is NOT allowed directly
// myDog.name = "Buddy"; // ERROR: 'name' is private
// Accessing private members through public member functions (getters/setters)
myDog.setName("Buddy");
cout << "My dog's name is: " << myDog.getName() << endl;
return 0;
}
This demonstrates encapsulation: the name
data member is hidden (private
) and can only be modified or retrieved through controlled methods (setName
, getName
), allowing the class to manage its own data integrity.
4. Differences between Structures, Unions, Enumerations and Classes
C++ provides several ways to group data and/or functions.
-
struct
(Structure): A user-defined composite data type that groups variables of different data types under a single name. In C++, astruct
is very similar to aclass
.- Key Difference from Class: By default, members of a
struct
arepublic
. - Like classes, structs in C++ can contain both data members and member functions.
- Key Difference from Class: By default, members of a
-
class
: A blueprint for objects, bundling data and methods.- Key Difference from Struct: By default, members of a
class
areprivate
.
- Key Difference from Struct: By default, members of a
struct Point {
int x; // public by default
int y; // public by default
};
class Circle {
double radius; // private by default
public:
double getRadius() { return radius; }
void setRadius(double r) { radius = r; }
};
int main() {
Point p;
p.x = 10; // OK, x is public by default
Circle c;
// c.radius = 5.0; // ERROR: radius is private by default
c.setRadius(5.0); // OK, using a public method
cout << c.getRadius() << endl; // OK, using a public method
return 0;
}
In C++, you can often use struct
and class
interchangeably, just remembering the default access difference. Conventionally, struct
is often used for simple data containers with mostly public members, while class
is used for more complex types involving encapsulation and methods.
-
union
: A special data type that allows storing different data types in the same memory location. Only one member of the union can hold a value at any given time. The size of a union is the size of its largest member. Unions are typically used for memory optimization or representing different types that are mutually exclusive at runtime. They can have member functions but are less common in typical OOP design compared to classes/structs.union Data { int i; float f; char str[20]; }; int main() { Data data; data.i = 10; cout << "data.i : " << data.i << endl; // data.f is now garbage because the memory was overwritten by data.i data.f = 220.5; cout << "data.f : " << data.f << endl; // data.i is now garbage // data.str = "C++ Programming"; // Cannot assign directly like this strcpy(data.str, "C++ Programming"); // Requires <cstring> cout << "data.str : " << data.str << endl; // data.i and data.f are now garbage return 0; }
-
enum
(Enumeration): A user-defined data type that consists of a set of named integer constants. It's used to make code more readable and maintainable by giving meaningful names to integer values.enum Day { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday }; int main() { Day today = Wednesday; cout << "Today is day number: " << today << endl; // Outputs the integer value (3) if (today == Wednesday) { cout << "It's Wednesday!" << endl; } return 0; }
Enums are distinct constants and are not related to the concept of bundling data and behavior like classes or structs.
5. Inline and Non-inline Member Functions
Member functions define the behavior of class objects.
-
Non-inline Member Functions: Defined outside the class definition. This is the standard way to define functions. The compiler generates a single copy of the function's machine code, and function calls involve a jump to the function's address.
-
Inline Member Functions: Defined inside the class definition or explicitly declared with the
inline
keyword outside the class. Theinline
keyword is a hint to the compiler. The compiler may choose to replace the function call with the actual body of the function code at compile time (function inlining). This avoids the overhead of a function call, potentially improving performance for small, frequently called functions, but can increase code size if the function is large or called many times.
5.1 Defining Member Functions
-
Inside the class definition (implicitly inline):
class Rectangle { private: double length; double width; public: // Constructor (usually defined inline) Rectangle(double l, double w) : length(l), width(w) {} // Member function defined inside the class (implicitly inline) double getArea() { return length * width; } // Another implicitly inline function double getPerimeter() { return 2 * (length + width); } }; // Semicolon after class definition
-
Outside the class definition (non-inline by default, can be explicitly inline):
- Use the scope resolution operator (
::
) to specify which class the function belongs to.
class Rectangle { private: double length; double width; public: Rectangle(double l, double w); // Constructor declaration double getArea(); // getArea declaration double getPerimeter(); // getPerimeter declaration // Can still have some inline functions inside void display() { cout << "Length: " << length << ", Width: " << width << endl; } }; // Semicolon // Definition of constructor outside the class (non-inline by default) Rectangle::Rectangle(double l, double w) : length(l), width(w) { cout << "Rectangle object created." << endl; } // Definition of getArea outside the class (non-inline by default) double Rectangle::getArea() { return length * width; } // Definition of getPerimeter outside, explicitly marked as inline inline double Rectangle::getPerimeter() { return 2 * (length + width); } int main() { Rectangle rect(10.0, 5.0); rect.display(); cout << "Area: " << rect.getArea() << endl; cout << "Perimeter: " << rect.getPerimeter() << endl; return 0; }
- Use the scope resolution operator (
When to use Inline:
- Small functions (e.g., simple getters/setters, single-line operations).
- Functions called frequently.
When NOT to use Inline:
- Large functions.
- Functions that are recursive.
- Functions that involve loops or switch statements (unless the compiler can optimize them).
- Functions where the address is taken.
The compiler makes the final decision whether to inline or not, regardless of the inline
keyword or definition location, but defining inside the class or using inline
provides a strong hint.
6. Static Data Members and Static Member Functions
Class members can be declared with the static
keyword. static
members belong to the class itself, rather than to any specific object of the class.
6.1 Static Data Members
- A static data member is shared by all objects of the class.
- There is only one copy of a static data member for the entire class, regardless of how many objects are created.
- Static data members must be defined and initialized outside the class definition, typically in the
.cpp
file. (Integral constants can be initialized inside the class).
class MyClass {
public:
int instanceData; // Belongs to each object
static int staticData; // Belongs to the class
MyClass(int data) : instanceData(data) {}
// Static member function to access static data
static int getStaticData() {
return staticData;
}
};
// Definition and initialization of the static data member outside the class
// The scope resolution operator (::) is used
int MyClass::staticData = 0;
int main() {
MyClass obj1(10);
MyClass obj2(20);
// Accessing instance data (each object has its own copy)
cout << "obj1 instanceData: " << obj1.instanceData << endl; // Output: 10
cout << "obj2 instanceData: " << obj2.instanceData << endl; // Output: 20
// Accessing static data (shared by all objects)
// Can access via an object or via the class name
obj1.staticData = 100;
cout << "obj2 staticData: " << obj2.staticData << endl; // Output: 100
MyClass::staticData = 200; // Preferred way to access static data
cout << "obj1 staticData: " << obj1.staticData << endl; // Output: 200
cout << "MyClass staticData: " << MyClass::staticData << endl; // Output: 200
return 0;
}
Static data members are useful for tracking class-wide information, like a counter for the number of objects created, or a shared configuration value.
6.2 Static Member Functions
- A static member function belongs to the class, not an object.
- They can be called using the class name and the scope resolution operator (
ClassName::staticFunction()
) or via an object (objectName.staticFunction()
), though the former is preferred. - A static member function can only access static data members and other static member functions of the same class. It does not have access to
this
pointer or instance-specific members because it is not called on a specific object.
class Counter {
private:
static int count; // Static data member to track object count
public:
Counter() {
count++; // Increment count whenever an object is created
cout << "Object created. Current count: " << count << endl;
}
~Counter() { // Destructor (called when an object is destroyed)
count--; // Decrement count when an object is destroyed
cout << "Object destroyed. Current count: " << count << endl;
}
// Static member function to get the current count
static int getCount() {
// return instanceData; // ERROR: Cannot access non-static member
return count; // OK: Can access static data member
}
};
// Definition and initialization of static data member
int Counter::count = 0;
int main() {
cout << "Initial count: " << Counter::getCount() << endl; // Access via class name
Counter c1; // count becomes 1
Counter c2; // count becomes 2
Counter c3; // count becomes 3
cout << "Current count: " << c1.getCount() << endl; // Access via object (less common)
cout << "Current count: " << Counter::getCount() << endl; // Preferred access via class name
{ // Create a block scope
Counter c4; // count becomes 4
cout << "Count inside block: " << Counter::getCount() << endl;
} // c4 goes out of scope and is destroyed, count becomes 3
cout << "Final count: " << Counter::getCount() << endl;
return 0;
} // c1, c2, c3 go out of scope and are destroyed, count becomes 0
Static member functions are useful for operations that relate to the class as a whole, such as factory methods, utility functions that operate on static data, or functions that provide class-wide information.
7. Features of Input/Output Streams
The C++ Standard Library provides a rich set of I/O capabilities through the iostream
library and the concept of streams.
-
Streams: Abstract representations of devices or files that produce or consume data. Data flows in sequences of bytes.
- Input Stream (
istream
): A source of data (e.g., keyboard, file).cin
is anistream
. - Output Stream (
ostream
): A destination for data (e.g., console, file).cout
,cerr
,clog
areostreams
.
- Input Stream (
-
Standard Streams:
cin
: Standard input stream (usually keyboard).cout
: Standard output stream (usually console).cerr
: Standard error stream (usually console, unbuffered). Used for reporting critical errors.clog
: Standard log stream (usually console, buffered). Used for logging program execution.
-
Stream Operations:
- Insertion (
<<
): Writes data to an output stream (cout
). - Extraction (
>>
): Reads data from an input stream (cin
). getline()
: Reads a line from an input stream.ignore()
: Discards characters from the input buffer.put()
: Writes a single character to an output stream.get()
: Reads a single character from an input stream.read()
: Reads a block of binary data.write()
: Writes a block of binary data.
- Insertion (
-
Stream Manipulators: Objects or functions used with
<<
or>>
to format or control stream behavior (e.g.,endl
,setw
,fixed
,precision
,boolalpha
). These will likely be covered in more detail in a later unit focused on I/O formatting. -
Stream States: Streams maintain state flags to indicate errors (e.g.,
failbit
,eofbit
,badbit
). You can check the state using methods likecin.fail()
,cin.eof()
,cin.good()
.
Understanding streams provides a consistent interface for handling various types of I/O in C++, from console to files (which are also treated as streams).
These notes cover the foundational elements of C++ programming and introduce the core concepts of classes and objects, setting the stage for deeper exploration of OOP principles in subsequent units. They align with the course outcomes by building basic programming skills (CO1), introducing code organization via classes (leading to reusability CO2), laying the groundwork for applying OOP principles (CO4), and providing tools for implementing code (CO5, CO6).