Study resource

Read at your pace, then save it for later.

Unit 2: Basics of C++: A Comprehensive Study Resource

C Vs C++

C++ is an extension of the C language, combining the power and efficiency of C with object-oriented programming (OOP) features. While C is a procedural programming language, C++ supports both procedural and object-oriented paradigms, making it a hybrid language. Understanding their differences is crucial for choosing the right tool for a task.

Key Concept: C++ is often called "C with Classes" because it extends C by adding features like classes, objects, inheritance, polymorphism, and abstraction, which are fundamental to OOP.
FeatureCC++
Programming ParadigmProcedural/Structured ProgrammingObject-Oriented, Procedural, Generic
ApproachTop-down approachBottom-up approach
Data SecurityLess secure (data can be accessed globally)More secure (data hiding via classes/objects)
Memory ManagementUses malloc(), calloc(), free()Uses new and delete operators (also supports C-style)
Error HandlingFunctions like setjmp() and longjmp()Exception handling (try, catch, throw)
Input/Outputscanf(), printf()cin, cout (via iostream library)
SupportDoes not support function overloading, operator overloading, or namespacesSupports function overloading, operator overloading, and namespaces

A Simple C++ Program

Let's begin with the classic "Hello, World!" program to understand the basic structure of a C++ program.

#include <iostream>

int main() {
    std::cout << "Hello, World!" << std::endl;
    return 0;
}

Explanation of the Simple C++ Program:

  • #include <iostream>: This is a preprocessor directive. It tells the compiler to include the iostream (input-output stream) library. This library contains functionalities for performing input and output operations, such as printing text to the console (std::cout) and reading input (std::cin).
  • int main() { ... }: This is the main function where the execution of any C++ program begins. Every C++ program must have a main function.
    • int indicates that the function will return an integer value upon completion.
    • main() is the name of the function. Parentheses () mean it takes no arguments in this simple case.
    • The curly braces { } define the body of the function, containing the statements to be executed.
  • std::cout << "Hello, World!" << std::endl;: This line performs the output operation.
    • std::cout is an object used to display output to the standard output device (usually the console).
    • << is the insertion operator, used to send data to std::cout.
    • "Hello, World!" is a string literal that will be printed.
    • std::endl is a manipulator that inserts a newline character and flushes the output buffer. It effectively moves the cursor to the next line.
  • return 0;: This statement indicates that the main function has successfully completed its execution. A return value of 0 conventionally signifies successful program termination.

Compiling & Linking

Before a C++ program can be executed, it needs to be translated from human-readable source code into machine-executable code. This process involves two main stages: compiling and linking.

The Compilation Process:

  1. Preprocessing: The preprocessor handles directives (like #include, #define). It expands macros, includes header files, and removes comments. The output is an expanded source file.
  2. Compilation: The compiler translates the preprocessed code into assembly language. This is architecture-specific code that is still human-readable to some extent.
  3. Assembly: An assembler translates the assembly code into machine code, which is a stream of instructions that the CPU can directly understand. This machine code is stored in an object file (e.g., .o or .obj). Object files are not directly executable because they often contain references to external functions or libraries that are not yet resolved.

Linking:

The linker takes one or more object files generated by the compiler/assembler and combines them with necessary library code (e.g., standard libraries like iostream, user-defined libraries) to produce a single, executable program. The linker resolves all symbol references between the different object files and libraries.

Example Command (using g++ compiler):
g++ myprogram.cpp -o myprogram
This command compiles myprogram.cpp and links it to create an executable file named myprogram. If there are multiple source files, e.g., file1.cpp and file2.cpp:
g++ file1.cpp file2.cpp -o myprogram
Or compile separately and then link:
g++ -c file1.cpp   // Compiles to file1.o
g++ -c file2.cpp   // Compiles to file2.o
g++ file1.o file2.o -o myprogram // Links object files

Tokens

Definition: In C++, a token is the smallest individual unit of a program that is meaningful to the compiler. The compiler breaks down a program into these tokens during the initial phase of compilation.

C++ tokens can be broadly classified into six types:

  • Keywords

    These are reserved words that have a predefined meaning and purpose in C++. They cannot be used as identifiers (names for variables, functions, etc.).

    • Examples: int, float, char, if, else, while, for, return, class, public, private, protected, void, const, new, delete.
  • Identifiers

    These are user-defined names given to various program elements such as variables, functions, classes, objects, structures, unions, and namespaces.

    • Examples: myVariable, calculateSum, MyClass, age.
  • Constants (Literals)

    These are fixed values that do not change during program execution. They are raw data assigned to variables or used directly.

    • Examples: 10 (integer), 3.14 (floating-point), 'A' (character), "Hello" (string), true (boolean).
  • Strings

    A sequence of characters enclosed in double quotation marks. They are treated as constant character arrays.

    • Examples: "Programming", "C++ is fun!".
  • Operators

    Symbols that perform specific mathematical, relational, logical, or bitwise operations on operands.

    • Examples: + (addition), - (subtraction), * (multiplication), / (division), % (modulo), = (assignment), == (equality), > (greater than), < (less than), && (logical AND), || (logical OR).
  • Special Symbols (Separators/Punctuators)

    Symbols that have syntactic or semantic meaning to the compiler, used for structuring code.

    • Examples: { } (block delimiters), ( ) (function arguments, grouping), [ ] (array indexing), ; (statement terminator), , (separator), : (scope resolution, labels), # (preprocessor directive), . (member access), -> (pointer to member access).

Identifiers & Constants

Identifiers

Definition: An identifier in C++ is a user-defined name given to a program entity, such as a variable, function, class, or object, to uniquely identify it within the program.

Rules for Naming Identifiers:

  • Identifiers must begin with a letter (a-z, A-Z) or an underscore (_).
  • After the initial character, identifiers can contain letters, digits (0-9), or underscores.
  • Identifiers are case-sensitive. For example, myVar and myvar are treated as two different identifiers.
  • Keywords (reserved words) cannot be used as identifiers.
  • No special characters (like !, @, #, %, ^, &, *, -, +) are allowed, except for the underscore.
  • There is no specific limit on the length of an identifier, but it's good practice to keep them reasonably short and meaningful.

Examples of Valid Identifiers:

  • score
  • total_amount
  • _userName
  • variable123
  • MyFunction

Examples of Invalid Identifiers:

  • 1stNumber (starts with a digit)
  • if (is a keyword)
  • my-variable (contains a hyphen)
  • sum&total (contains an ampersand)

Constants (Literals)

Definition: Constants, also known as literals, are fixed values that are directly embedded into the program's source code. Their values cannot be changed during the execution of the program.

C++ supports various types of constants:

  • Integer Literals

    Whole numbers without a fractional part.

    • Decimal: 10, -5, 1000
    • Octal (prefix 0): 012 (decimal 10), 077
    • Hexadecimal (prefix 0x or 0X): 0xA (decimal 10), 0xFF
    • Suffixes: L or l for long, LL or ll for long long, U or u for unsigned. (e.g., 100L, 200ULL)
  • Floating-Point Literals

    Numbers with a fractional part, or numbers expressed in exponential form.

    • Examples: 3.14, -0.001, 2.5e-3 (2.5 × 10-3), 1.23E+5 (1.23 × 105)
    • Suffixes: f or F for float, l or L for long double (e.g., 3.14f)
  • Character Literals

    A single character enclosed in single quotation marks.

    • Examples: 'A', 'x', '5', '\n' (newline escape sequence)
  • String Literals

    A sequence of characters enclosed in double quotation marks.

    • Examples: "Hello", "C++ Programming"
  • Boolean Literals

    Represent truth values.

    • Examples: true, false
  • Defining Named Constants (using const keyword)

    The const keyword is used to declare variables whose values cannot be changed after initialization. This is the preferred method for creating named constants in modern C++.

    const int MAX_ATTEMPTS = 3;
    const double PI = 3.14159;
    
    // MAX_ATTEMPTS = 5; // This would result in a compilation error.

Data Types

Definition: A data type specifies the type of data that a variable can hold. It determines the size and layout of the variable's memory, the range of values it can store, and the set of operations that can be applied to it.

C++ data types are categorized into three main types:

  • Built-in (Fundamental) Data Types

    These are basic data types provided by the language itself.

    • int: Used to store whole numbers (integers).
      • Size: Typically 4 bytes (can vary based on system architecture).
      • Range: Approx. -2 × 109 to 2 × 109.
    • char: Used to store single characters or small integers.
      • Size: 1 byte.
      • Range: -128 to 127 or 0 to 255 (depending on signed/unsigned).
    • float: Used to store single-precision floating-point numbers (numbers with decimal points).
      • Size: Typically 4 bytes.
      • Precision: Approx. 7 decimal digits.
    • double: Used to store double-precision floating-point numbers. Offers more precision than float.
      • Size: Typically 8 bytes.
      • Precision: Approx. 15 decimal digits.
    • bool: Used to store boolean values (true or false).
      • Size: 1 byte (can be optimized to less).
      • Values: true (usually 1), false (usually 0).
    • void: An incomplete type meaning "no type" or "absence of type". It is used in specific contexts, such as function return type when no value is returned, or as a generic pointer (void*).
    • wchar_t: Wide character type, used for characters that require more storage than a typical char (e.g., Unicode characters).

    Data Type Modifiers: These keywords can alter the range and/or size of fundamental data types.

    • signed: Can store both positive and negative values (default for int, char).
    • unsigned: Can store only non-negative (zero or positive) values. Doubles the positive range.
    • short: Guarantees at least 2 bytes (for int).
    • long: Guarantees at least 4 bytes (for int) or 8 bytes (for double).

    Common Combinations:

    • short int (or simply short)
    • long int (or simply long)
    • long long int (or simply long long)
    • unsigned int
    • unsigned char
    • long double
  • Derived Data Types

    These data types are built upon or derived from fundamental data types.

    • Arrays: A collection of elements of the same data type stored at contiguous memory locations.
    • Pointers: Variables that store memory addresses of other variables.
    • References: Aliases to existing variables (discussed in the next section).
    • Functions: Blocks of code designed to perform a specific task.
  • User-Defined Data Types

    These data types are created by the programmer.

    • Classes: Blueprints for creating objects, encapsulating data and functions.
    • Structures (struct): Similar to classes but members are public by default.
    • Unions (union): Allow different data types to share the same memory location.
    • Enumerations (enum): Assign names to integer constants, making code more readable.

Reference Variables

Definition: A reference variable in C++ is an alias (an alternative name) for an already existing variable. It provides another way to access the same memory location as the original variable. Once a reference is initialized to a variable, it cannot be reseated to refer to another variable.

Declaring and Initializing Reference Variables:

References are declared using the ampersand symbol (&) after the type, and they must be initialized at the time of declaration with an existing variable.

int originalVar = 10;
int &refVar = originalVar; // refVar is now an alias for originalVar

// You cannot do this:
// int &anotherRef;        // Error: references must be initialized
// int yetAnotherVar = 20;
// refVar = yetAnotherVar; // This assigns the VALUE of yetAnotherVar to originalVar, not reseating refVar

Key Characteristics of Reference Variables:

  • Alias: A reference is simply another name for an existing variable. Any operation performed on the reference variable is actually performed on the original variable.
  • Initialization is Mandatory: A reference must be initialized when it is declared. It cannot be declared without being bound to a variable.
  • Cannot be Reseated: Once a reference is initialized to an object, it cannot be changed to refer to another object. It will always refer to the object it was initially bound to. (Attempting to assign a different variable to a reference will assign the *value* of that variable to the original variable the reference points to).
  • No Null References: A reference cannot be null. It must always refer to a valid memory location.
  • No Address-of Operator on References: You cannot take the address of a reference variable using & to get the address of the reference itself; instead, &refVar gives the address of the original variable.

Example Usage:

int score = 100;
int &playerScore = score; // playerScore is now an alias for score

std::cout << "Original score: " << score << std::endl;      // Output: 100
std::cout << "Reference score: " << playerScore << std::endl; // Output: 100

playerScore = 150; // Changing playerScore also changes score

std::cout << "Updated original score: " << score << std::endl;      // Output: 150
std::cout << "Updated reference score: " << playerScore << std::endl; // Output: 150

std::cout << "Address of score: " << &score << std::endl;
std::cout << "Address of playerScore: " << &playerScore << std::endl;
// Notice that both addresses will be the same, confirming they refer to the same memory location.

Difference from Pointers:

While references provide indirect access to variables like pointers, they have key distinctions:

  • Syntax: References use &, pointers use *.
  • Initialization: References must be initialized; pointers can be declared without initialization (but should be initialized to nullptr or a valid address to avoid undefined behavior).
  • Reseating: References cannot be reseated; pointers can be made to point to different variables.
  • Null Value: References cannot be null; pointers can be null.
  • Dereferencing: References are used directly (like the original variable); pointers require dereferencing (*ptr) to access the value they point to.
  • Memory: Compilers might implement references using addresses internally, but from a programmer's perspective, references directly access the variable without needing a separate memory address variable.

xxx

Did this help you understand better?

Your feedback improves the quality of this resource for everyone.