Fresher interview questions
C++ began as an extension of the C language, adding object oriented features such as classes, inheritance, and polymorphism on top of the procedural style C already offered. C keeps you working with plain functions and structures, while C++ lets you group data and the functions that operate on it into a single class. C++ also added templates, exception handling, and a much larger standard library, making it a more expressive language for large, structured applications.
A compiler translates an entire program into machine code before anything runs, producing a standalone executable file that the operating system can launch directly. An interpreter instead reads and executes a program line by line, without ever producing a separate binary file. C++ is a compiled language, which is a major reason its programs tend to run faster than those written in purely interpreted languages, since all the translation work happens once, ahead of time, rather than repeatedly during execution.
The core built in types include int for whole numbers, double and float for numbers with a decimal point, char for a single character, and bool for a true or false value. Each type reserves a specific amount of memory and supports a particular range of values, so choosing the right one affects both how much memory a program uses and how precise its calculations can be. Text made of multiple characters typically uses the string type from the standard library rather than one of these basic types.
int stores whole numbers only, with no fractional part, while float stores numbers that include a decimal component, though with limited precision compared to double. Dividing two int values in C++ produces another whole number, discarding anything after the decimal point, which surprises many newcomers expecting a fractional result. Choosing float or its more precise cousin double becomes necessary whenever a calculation genuinely needs fractional accuracy, such as measurements, prices, or scientific values.
A declaration tells the compiler that a name exists and states its type, without necessarily reserving memory for it, which matters most for functions and variables shared across multiple files. A definition actually allocates storage for that variable or provides the body of a function. For an ordinary local variable these two things usually happen together on the same line, but the distinction becomes important once a program spans several source files that need to share the same variable or function safely.
main is the designated starting point of every standalone C++ program; the operating system looks for this specific function and begins execution there once the program is launched. Everything the program does eventually traces back to calls made from inside main, whether directly or through other functions it invokes. It typically returns a whole number back to the operating system, where a zero conventionally signals that the program finished successfully and anything else signals some kind of failure.
A pointer is a variable that stores the memory address of another variable rather than holding a value like a number or piece of text directly. Instead of asking what value is stored here, a pointer answers where is this value actually located in memory. Once you have a pointer to something, you can follow it to read or change the original value indirectly, which is genuinely useful once a program needs to share or modify the same piece of data from more than one place.
A reference acts as another name for an existing variable rather than a completely separate variable that stores an address. Once created, a reference cannot be made to refer to a different variable later, whereas a pointer can be reassigned to point somewhere else at any time. References also cannot be left unset the way a pointer can be left empty, which generally makes them a little safer and simpler to reason about whenever you do not need a pointer's extra flexibility.
Passing by value copies the argument into the function, so any changes made inside the function have no effect on the original variable back where it was called from. Passing by reference instead gives the function direct access to the original variable, so changes made inside genuinely affect it outside as well. Pass by value is the safer default for small values like numbers, while pass by reference avoids unnecessary copying for larger data and is needed whenever a function must modify the caller's variable.
Marking a variable const tells the compiler that its value must never change after it is initially set, and any attempt to reassign it later becomes a compile time error rather than a runtime surprise. It can also be applied to function parameters to promise that a function will not modify the data it was given, and to member functions to promise they will not modify the object they belong to. This makes intent explicit and lets the compiler catch accidental changes early.
A plain array has a fixed size chosen at the moment it is created and cannot grow or shrink afterward, and it does not track its own length, so a separate variable is usually needed alongside it. A vector, part of the standard library, can grow and shrink as items are added or removed, and it always knows its own size internally. Because of this added flexibility and safety, most modern C++ code reaches for a vector by default and only uses a plain array when there is a specific reason to.
A class is a user defined blueprint that bundles together data, called member variables, and the functions that operate on that data, called member functions, into a single unit. It describes a general shape for something, such as a bank account or a shape on screen, without yet being an actual instance of it. Classes are the foundation of object oriented programming in C++, letting a program model real world concepts as self contained, reusable pieces of code.
An object is a concrete instance created from a class blueprint, occupying its own memory and holding its own particular values for whatever member variables the class defines. Many separate objects can be created from the very same class, each independent of the others, similar to how many individual houses can be built from one architectural plan. Creating an object typically triggers the class's constructor, which sets up that specific object's starting state.
A constructor is a special member function that runs automatically the moment an object is created, and its main job is to set the object up with sensible starting values. It shares its name with the class itself and has no return type at all, not even void. A class can define several constructors accepting different sets of arguments, letting an object be created in more than one way depending on what information is available at the time.
A destructor is a special member function that runs automatically just before an object is destroyed, whether that happens because it goes out of scope or is explicitly deleted. It is named after the class with a tilde in front, takes no arguments, and is typically used to release any resources the object was holding, such as memory it allocated itself or a file handle it opened, so that nothing is left behind once the object disappears.
A constructor runs at the beginning of an object's life to set it up, and it can accept parameters and be overloaded so several versions exist for different situations. A destructor runs at the very end of an object's life to clean it up, takes no parameters, and a class can only ever have exactly one. In short, one prepares an object for use while the other guarantees it is torn down properly once it is no longer needed.
Function overloading lets a program define several functions that share the same name but differ in the number or types of parameters they accept. When the function is called, the compiler figures out which specific version was intended by comparing the arguments provided against each overload's parameter list. This is useful when an operation conceptually means the same thing regardless of the input type, such as adding two whole numbers versus adding two decimal numbers, without needing separate, differently named functions for each case.
Yes, a C++ function can specify a default value for one or more of its trailing parameters, and a caller who omits that argument automatically receives the specified default instead. This reduces the need to write several overloaded versions of a function purely to handle optional arguments. Default values must be provided for parameters starting from the right hand side of the parameter list onward, since the compiler needs to unambiguously match whichever arguments are actually supplied.
The scope resolution operator, written as two colons together, is used to specify exactly which scope a name belongs to when there could otherwise be ambiguity. It commonly appears when defining a class's member function outside the class body, tying that definition back to the correct class, and it is also used to access something inside a namespace, such as reaching a name that belongs to the standard namespace rather than one defined locally in the current file.
Members marked public can be accessed from anywhere outside the class, private members can only be accessed from within the class itself, and protected members behave like private ones except that they remain accessible to derived classes that inherit from the class. Choosing the right access level is central to encapsulation, since keeping internal details private while exposing only a clean public interface prevents outside code from depending on, or accidentally breaking, implementation details that might later change.
Inheritance lets one class, called the derived class, reuse the fields and functions already defined by another class, called the base class, without rewriting them from scratch. The derived class automatically gains everything the base class offers and can add its own additional behaviour, or replace some of the inherited behaviour with its own version. This models real world is a relationships well, such as a savings account being a specific kind of bank account that shares most of the same basic behaviour.
Functionally, struct and class are almost identical in C++, since both can hold data, define functions, and support inheritance. The only real difference is the default access level: members of a struct are public unless stated otherwise, while members of a class are private unless stated otherwise. By convention, many C++ programmers still use struct for simple, data only groupings with little or no behaviour, and reserve class for types that combine data with meaningful behaviour and encapsulation.
A header file typically holds declarations, such as function signatures and class definitions, that describe what a piece of code offers without necessarily containing its full implementation. Including a header file lets one source file use classes or functions defined elsewhere without needing to see or recompile their actual implementation every time. This separation between declaration and implementation is central to how larger C++ projects stay organised across many files while still compiling efficiently.
Include guards are a small block of preprocessor directives placed at the top of a header file that prevent its contents from being processed more than once if it happens to be included, directly or indirectly, several times within the same source file. Without them, a header included twice can cause the compiler to see the same class or function declared repeatedly, producing confusing duplicate definition errors. Modern code often uses a single pragma once directive as a simpler, equivalent alternative.
Declaring a function tells the compiler its name, return type, and parameter types, essentially describing its signature so other code can call it before its actual implementation has even been written or compiled yet. Defining a function provides the actual body containing the logic that runs when it is called. Header files typically hold declarations so multiple source files can call a function, while exactly one source file holds its single definition.
Stack memory holds ordinary local variables and is managed automatically: as soon as the function that created them finishes, that memory is instantly and safely reclaimed with no extra effort from the programmer. Heap memory is a separate pool that a program can request from at any time, and anything placed there survives until it is explicitly released, or until the program ends. Heap memory offers more flexibility for data that must outlive a single function, but it comes with the added responsibility of eventually freeing it.
The new keyword requests a block of memory from the heap, large enough to hold whatever type is specified, constructs an object there if applicable, and returns a pointer pointing at that freshly allocated memory. Unlike memory for an ordinary local variable, memory obtained through new is not automatically cleaned up when the surrounding function ends; it continues to exist until it is explicitly released, which is exactly the behaviour that makes the heap useful for data that needs to outlive a single function call.
The delete keyword releases memory that was previously obtained with new, running the appropriate destructor first if the memory held an object, and then returning that memory back to the system so it can be reused elsewhere. Forgetting to call delete on memory you allocated yourself causes a memory leak, since that space remains reserved for the rest of the program's lifetime even though nothing can reach it any longer. Every call to new should be matched by exactly one corresponding delete.
A null pointer is a pointer that has been deliberately set to point at nothing at all, rather than at any valid piece of memory. It is commonly used to signal that a pointer is not currently usable, such as before it has been assigned a real address, or after the memory it once pointed to has already been released. Attempting to read or write through a null pointer, known as dereferencing it, is a serious error that typically crashes the program immediately.
An array index in C++ actually represents an offset, meaning how many elements away from the very first element you want to reach, rather than a position number in the everyday counting sense. The first element sits exactly at the array's starting address, zero elements away from itself, which is why it is indexed with zero. This offset based approach also makes the underlying pointer arithmetic that arrays rely on simpler and more consistent, even though it does take some getting used to for newcomers.
The standard string type manages its own memory automatically, can grow or shrink as needed, and provides many convenient built in operations such as concatenation, searching, and comparison. A plain character array has a fixed size decided at creation time, requires a special terminating character to mark where the text ends, and offers none of those convenience operations directly. Modern C++ code almost always prefers the string type unless there is a specific low level reason to work with raw character arrays instead.
A while loop checks its condition before running the loop body, so if the condition is false right from the start, the body never executes even once. A do while loop checks its condition after running the body, guaranteeing that the body always executes at least one time regardless of the condition. This makes do while a natural fit for situations like prompting a user for input, where you want to ask at least once before deciding whether to ask again.
break immediately exits the loop entirely, skipping any remaining iterations and moving execution to whatever comes right after the loop. continue instead skips only the rest of the current iteration and jumps straight to the loop's next check or increment step, allowing the loop to keep going. break is typically used once a search has already found what it needed, while continue is used to skip handling for certain values without abandoning the whole loop.
Operator overloading lets a programmer define what a familiar symbol, such as the plus sign, means when applied to objects of a custom class, rather than only the built in numeric types. For example, a class representing a point in two dimensional space could overload the plus sign so that adding two point objects together produces a new point with combined coordinates, making the code that uses the class read naturally, much like ordinary arithmetic on numbers.
A friend function is a function that is not a member of a class but is still granted access to that class's private and protected members, because the class explicitly declares it as a friend. This is occasionally useful when an operation naturally involves two classes equally and does not belong more to one than the other, such as comparing two different types together. Friend access should be used sparingly, since it deliberately breaks the usual encapsulation boundary a class provides.
An object created directly as a local variable lives on the stack and is destroyed automatically the instant the function it was created in returns, with no extra work required. An object created with the new keyword lives on the heap and continues to exist, taking up memory, until it is explicitly deleted, potentially long after the function that created it has already finished. Stack objects are simpler and safer by default, while heap objects offer more control over exactly how long something lives.
Call by value copies the actual argument into the function's parameter, so changes made inside only affect that local copy and never the original variable. Call by pointer instead passes the memory address of the original variable, letting the function follow that address to read or modify the original value directly. Call by pointer requires explicitly dereferencing the pointer to reach the underlying value, which is one reason many modern C++ programmers prefer references for this same purpose when a pointer's extra flexibility is not required.
The sizeof operator reports how much memory, measured in bytes, a particular type or variable occupies, and it is evaluated by the compiler rather than at runtime whenever possible. It is commonly used to calculate how many elements fit in a fixed size array, to help allocate the correct amount of raw memory, or simply out of curiosity about how a given type is represented internally. Its exact result can vary between different compilers and target platforms, so it should never be assumed to be a fixed universal number.
A namespace is a named region that groups related names, such as classes and functions, together under one label, preventing naming clashes between code written by different authors or different libraries. Two functions with the exact same name can coexist peacefully as long as they live inside different namespaces, since the namespace becomes part of how that name is uniquely identified. This becomes especially valuable in larger projects that combine code from several different libraries, each of which might otherwise choose overlapping names.
std is the namespace that holds essentially the entire C++ standard library, including familiar tools like the string type, the vector container, and the input and output streams used for printing to the console. Referring to something like the string type by its full name means explicitly qualifying it with the std namespace in front, though many programs bring the whole namespace into scope at once for convenience, a habit that is generally discouraged in larger codebases because it increases the risk of naming collisions.
A local variable is declared inside a function or block and only exists, and is only visible, while that function or block is executing, after which it is automatically destroyed. A global variable is declared outside every function, exists for the entire lifetime of the program, and can potentially be accessed and modified from anywhere in the code. Relying heavily on global variables generally makes a program harder to reason about, since any part of the code could be silently changing shared state.
Recursion is a technique where a function calls itself, either directly or indirectly, in order to break a problem down into smaller versions of the exact same problem until it reaches a simple case that can be answered directly, known as the base case. A classic example is calculating a factorial, where the factorial of a number is defined in terms of the factorial of a smaller number. Every recursive function needs a clearly reachable base case, or it will keep calling itself indefinitely and eventually crash the program.
The return statement immediately ends execution of the current function and, if the function has a non void return type, hands a value back to whatever code called it. Once a return statement runs, no further lines inside that function execute, even if there is more code written below it. A function declared to return void can still use a bare return statement with no value, simply to exit early without producing a result.
Type casting is the process of explicitly converting a value from one type to another, such as turning a decimal number into a whole number, or treating one kind of pointer as another. C++ offers several distinct casting operators, including static cast for straightforward, generally safe conversions and reinterpret cast for low level, potentially unsafe reinterpretations of memory, giving programmers finer control and more safety than the older, less specific style of casting inherited from C.
An implicit conversion happens automatically, without the programmer writing anything special, such as when an integer is used somewhere a decimal number is expected and the compiler quietly promotes it. An explicit conversion requires the programmer to deliberately request the conversion using a cast, making the intent clear in the code itself. Explicit conversions are generally considered safer for anything beyond a very obvious, lossless conversion, since they force a programmer to consciously acknowledge that a conversion, and any potential loss of information, is happening.