DEV Community

Cover image for C++ coding interview questions for beginners
Hunter Johnson for Educative

Posted on • Originally published at educative.io

C++ coding interview questions for beginners

C++ is a general-purpose programming language that was developed in 1979 by Bjarne Stroustrup. C++ was born as an object-oriented superset of C. According to the Stack Overflow Developer Survey, C++ is one of the top six most popular programming languages. It is primarily used as an object-oriented programming (OOP) language.

Some C++ characteristics:

  • Platform dependent: If a program is written and compiled on a particular operating system, it may not run on any other operating system.
  • Compiled: A compiler is required for all code written in C++ to be executed.
  • Multi-paradigm: While C++ is capable of object-oriented programming, it isn't solely an OOP language. C++ still incorporates traditional “C style” programming.
  • Structured: Like all modern programming languages, C++ can be divided into sections using control flow statements, loops, and functions.
  • Rich library: There are plenty of built-in functions through the Standard Template Library (STL).
  • Highly optimizable: C++ memory management and low-level syntax allow a programmer to write highly optimized code that may have a significantly smaller memory footprint and run faster as compared to almost all other programming languages.

We'll cover:

  • What is OOP?
  • How to prepare for a coding interview
  • 20 C++ coding interview questions for beginners
  • Next steps to nail any coding interview

What is object-oriented programming (OOP)?

Object-oriented programming is a programming paradigm that organizes programs around objects, where each object may contain data and relevant functions. The person responsible for coining the term "object-oriented programming," Alan Kay, stresses the importance of messaging for communication between objects.

That said, the relationship between objects is the foundation of object-oriented programming.

The four pillars of OOP are:

  • Abstraction: Abstraction refers to the ability of a class to hide its internal implementation details and expose only its essential features to the outside world. This allows users of an object of that class to interact with it without needing to know its internal workings.

  • Encapsulation: Encapsulation refers to the idea of keeping the internal state (i.e. current values of attributes) and behavior of an object hidden from the outside world while providing a public interface for interacting with it. This allows the class or object to control access to its internal data and behavior, and protect it from being modified or accessed in an unintended way.

  • Inheritance: Two classes (say Car, and Toyota) have the inheritance relationship between them when one class, say Toyota, is extending the other class (Car). In this example, Car will be referred to as a base-class or a superclass whereas Toyota will be referred to as a derived-class or subclass. Inheritance allows a derived class to take some of the attributes and methods of the base class. Moreover, the derived class may enhance the base class by introducing additional attributes and methods. Inheritance promotes code reusability and extensibility.

  • Polymorphism: Polymorphism allows objects of different classes to be treated as objects of one of their common superclasses. This enables methods to be defined on the superclass to be overridden by subclasses to provide their own implementation. Thus, a single method call can be executed on objects of multiple classes, with the appropriate implementation being called based on the actual class of the object.

Abstraction vs. Encapsulation: The difference between abstraction and encapsulation is commonly misunderstood. Abstraction is about hiding complexity and only showing the essential features, while encapsulation is about protecting the internal state and behavior of an object and controlling access to it.

How to prepare for a coding interview

It’s no secret you have to practice, but five out of six interviewers will fail a coding interview. So, how do you practice effectively? There are two main schools of thought when it comes to coding interview prep:

  • The LeetCode approach: Drill as many problems as possible in the hopes that one you’re familiar with is asked in an interview.

  • Pattern-based approach: Learn a total of 24 patterns that teach how to recognize, diagnose, and solve any interview question you may be presented with.

20 C++ interview questions for freshers

Below is a list of questions we have compiled not to represent the popular C++ questions that are asked by interviewers but to give you an idea of the types of content you should be reviewing.

Note: We have only recorded one example answer, but there are multiple correct responses to most of these questions.

1. What are the main differences between C and C++?

As mentioned above, C++ was developed as a superset of C. C++ was originally called "C with classes," and the original goal was to create a version of C that facilitated an object-oriented model without compromising speed or low-level functionality. C++ is able to combine the procedural functionality of C with the flexibility and usability of OOP.

2. What are classes and objects in C++?

Classes and objects are not a feature of C++ in particular. They are integral to all object-oriented programming languages. A class is like a blueprint that does not exist during program execution. However, based on a class design, at runtime, we can create its object(s). An object has the same attributes and methods which were defined in its class. Let’s see a simple example of creating a class and making its objects in C++:

Attribute vs. Variable: An attribute is a variable defined in a class.

#include <iostream>

class Car {
   public:
   /**
    * The attributes of class Car.
   */
   int number;
   int year;

   /*
    * The methods of class Car.
    */

   int getNumber() {
       return number;
   }
   int getYear() {
       return year;
   }
   void setNumber(int number) {
       this->number = number;
   }
   void setYear(int year) {
       this->year = year;
   }


};


int main() {
   /**
    * Creating object of the class Car
    */
   Car myCar;

   // Using the car object
   myCar.setNumber(777);
   myCar.setYear(2018);

   //Printing its attributes
   std::cout << "My car number and manufacturing year are: " << myCar.number << ", " << myCar.year << "\n";


   return 0;
}
Enter fullscreen mode Exit fullscreen mode
//output
My car number and manufacturing year are: 777, 2018
Enter fullscreen mode Exit fullscreen mode

3. What is a constructor in C++?

A constructor is a special function of a class which is called automatically upon creation of an object. Thus, a constructor usually outline the steps that occur when one instance of a class is created.

A constructor's name must be the same as it's class name.

Put simply, constructors can create and initialize objects of their class type. They cannot be classified as volatile or static nor can the body of a constructor contain a return statement.

The following code playground demonstrates the creation and use of a class’s constructors:

#include <iostream>

class Car {
   public:
   /**
    * The attributes of class Car.
   */
   int number;
   int year;

   /**
    * An empty constructor of the class Car
    */
    Car() {
        std::cout << "Constructor-A is called\n";
    }

   /**
    * Another constructor of the class Car
    */
    Car(int number, int year) {
        std::cout << "Constructor-B is called\n";
        this->number = number;
        this->year = year;
    }

   /*
    * The methods of the class Car.
    */

   int getNumber() {
       return number;
   }

   int getYear() {
       return year;
   }

   void setNumber(int number) {
       this->number = number;
   }

   void setYear(int year) {
       this->year = year;
   }


};


int main() {
   /**
    * Creating object of the class Car and using its constructor
    */
   Car myCar(777, 2018);

   //Printing its attributes
   std::cout << "My car number and manufacturing year are: " << myCar.number << ", " << myCar.year << "\n";


   return 0;
}
Enter fullscreen mode Exit fullscreen mode
//output
Constructor-B is called
My car number and manufacturing year are: 777, 2018
Enter fullscreen mode Exit fullscreen mode

4. Explain the difference between struct and class

Also called structs, structures serve as a way to group related variables together. Each variable is known as a member of the structure.

Structures are created with the struct keyword and members are declared within curly braces.

C++ structure is very similar to class. However, a key difference is that class attributes are by default 'private' whereas struct attributes are by default 'public'. Thus, by default 'struct' attributes can be directly accessed and modified.

5. What does the this pointer do?

A pointer is a variable that stores the address of another variable. The this pointer is only accessible in non-static member functions of classes, structs, or unions. It refers to the object on which the member function is called.

There are several use cases for the this pointer.

  • Current object: the this pointer can be used to return the reference of the calling object.
  • Same name: If a parameter and private function both have the same name, the this pointer can be used to distinguish between the two when assigning values.

The this pointer is always passed to the constructor as it holds the address of the object being constructed. If you're interested, we have some example code on Educative Answers.

6. What are the three main access specifiers in C++?

Access specifiers define how different variables and functions that are contained within a class can be accessed.

  • public: A public attribute or function of a class can be accessed outside of that class
  • private: A private attribute or function of a class cannot be accessed outside of that class
  • protected: A protected attribute or function of a class cannot be accessed outside of that class, except the subclasses of that class.

7. What is a friend class? Why is this useful?

A class can declare other classes as a friend, and as a result, a friend class can then access the private and protected members of that class. This is important as it facilitates encapsulation of the non-relevant elements of a data structure to the user but extends the storage and access to component parts.

Friend functions are primarily important in expanding the functionality of data structures like linked lists. A linked list class may be declared as a friend to access private members of a node.

8. Describe the four pillars of object-oriented programming

The four pillars of OOP, as discussed earlier in this article, are: abstraction, encapsulation, inheritance, and polymorphism.

Here we’ll cover the very basics of each pillar, but we recommend looking over the above section dedicated to OOP if you need a more thorough explanation.

  • Abstraction: Some of an object’s properties and methods are hidden from outside observation.

  • Encapsulation: Related variables and functions are grouped into objects based on a larger blueprint called a class.

  • Inheritance: Some of the properties and methods of one object may be passed down to another object.

  • Polymorphism: Literally “many forms,” polymorphism refers to objects that respond in different ways to the same function.

9. What is overloading and overriding in C++?

Function overloading or function overriding are examples of different kinds of polymorphism in C++ (see the question about compile-time and runtime polymorphism). Both serve as different ways to simplify the interface and make programs more intuitive to use and write. Function overloading and overriding are similar-sounding terminologies, having vastly different characteristics. Therefore, this question is frequently asked in coding interviews and is commonly answered incorrectly. Let’s understand it clearly with examples.

Overloading refers to the functions of the same scope (such as a class scope or the global scope) having the same name but different parameters. For example, in the code below, we have two functions defined in a global scope where both functions have the same name, printMulti, but different parameters.

#include <iostream>


void printMulti(int x, int y) {
   std::cout << x * y << std::endl;
}


void printMulti(double x, double y) {
   std::cout << x * y << std::endl;
}


int main() {
   printMulti(3, 5);  // Automatically calls the first function
   printMulti(3.1, 5.2);  // Selects to calls the second function
   return 0;
}
Enter fullscreen mode Exit fullscreen mode
//output
15
16.12
Enter fullscreen mode Exit fullscreen mode

Overriding When a superclass function is rewritten (with exactly the same name, parameters, and return type) in a subclass but having different implementation, we refer to the subclass function overriding the superclass function and this technique is referred to as function overriding. A same function may be overridden multiple times in different subclasses. In the example below we have the Shape superclass and its two subclasses Rectangle and Circle. A function calc_circumference is virtual in the superclass but have different implementations in the subclasses.

#include <iostream>


class Shape {
public:
   virtual double calc_circumference() = 0;
};


class Rectangle : public Shape {
private:
   double width;
   double height;
public:
   Rectangle(double w, double h) {
       width = w;
       height = h;
   }
   //Overriding function of the base class
   virtual double calc_circumference() {
       return 2*width*height;
   }
};


class Circle : public Shape {
private:
   double radius;

public:
   Circle(double r) {
       radius = r;
   }
   //Overriding function of the base class
   virtual double calc_circumference() {
       return 2*3.14*radius;
   }
};


int main() {
   int width = 3, height = 4;
   double radius = 3;

   //Ah! This is polymorphism where Shape objects could be of either type: Rectangle and Circle.
   // The function being called depends on the object initiation.
   Shape *shape1 = new Rectangle(width, height);
   Shape *shape2 = new Circle(radius);


   std::cout << "Rectangle with width="<<width<<", height= "<< height << " has area="<<shape1->calc_circumference()<<  std::endl;  // calls the Rectangle's implementation
   std::cout << "Circle with radius="<<radius<< " has area="<<shape2->calc_circumference() << std::endl;  // calls the Circle's implementation

   //Do not forget to free the memory
   delete shape1;
   delete shape2;


   return 0;
}
Enter fullscreen mode Exit fullscreen mode
//output
Rectangle with width=3, height= 4 has area=24
Circle with radius=3 has area=18.84
Enter fullscreen mode Exit fullscreen mode

10. What is the difference between compile time polymorphism and runtime polymorphism?

In C++, polymorphism refers to the ability of objects of different classes to respond to the same method call in different ways. There are two main types of polymorphism in C++: compile-time polymorphism and runtime polymorphism.

Compile-time polymorphism, also known as static polymorphism, is implemented through function overloading and operator overloading. Function overloading allows multiple functions with the same name but different parameter lists to be defined in the same scope.

Runtime polymorphism, also known as dynamic polymorphism, is implemented through inheritance and virtual functions. Inheritance allows classes to inherit properties and behaviors from their base classes. Virtual functions allow derived classes to override the implementation of a base class method so that objects of the derived class can respond to the same method call in different ways. The actual implementation of a virtual function is determined at runtime based on the actual type of the object, not just the declared type.

11. What does the new operator do?

The new operator is used for dynamic memory allocation. The operator denotes a request for allocating memory to the Heap. If the memory is available, it is initialized and then the pointer to the newly allocated memory is returned. The code below creates an array dynamically based on the input size which could be taken at runtime from a user.

#include <iostream>


int main() {
   //The size value can be decided at runtime via a user's input
   int size = 10;
   //The array is created at the runtime (a.k.a dynamic memory allocation).
   int *array = new int[size];


   std::cout<<"Address of dynamically created array = "<<(void *)array << "\n";
   return 0;
}
Enter fullscreen mode Exit fullscreen mode
//output
Address of dynamically created array = 0x20a0c20
Enter fullscreen mode Exit fullscreen mode

12. What is a variable's scope? What does it mean for a variable to be local?

The scope of a variable relates to the block of code the variable is contained within. Where, the block may refer to a function, program, loop, or any code placed between opening and closing curly braces. There are two main designations when it comes to the scope of a given variable:

  • Local: These variables are accessible only within the block of code that they are declared.
  • Global: These variables are declared outside of a program and therefore accessible throughout the program.

The following code playground demonstrates local scope to a function and an if-block. Moreover, it also shows a variable with the global scope.

#include <iostream>


//g_x is a global variable
int g_x = 10;


int foo(int ilocal) {
   //ilocal and jlocal both are local variables to the foo function
   int jlocal = 5;
   if (ilocal < 5) {
       // the scope of flocal is this if-block
       int flocal = 10;
       ilocal = flocal;
   }
   std::cout << "We cannot access flocal outside the above if-block" << '\n';
   return jlocal+ilocal;
}
int main() {
   int llocal = foo(20);
   std::cout << "We cannot access ilocal and jlocal outside the foo function" << '\n';
   // But we can access the global variable g_x here
   std::cout << "Value of global variable is=" << g_x << '\n';
   //We can access llocal here as it scope is the current function
   std::cout << "Value of local variable to main() is=" << llocal;
   return 0;
}
Enter fullscreen mode Exit fullscreen mode
//output
We cannot access flocal outside the above if-block
We cannot access ilocal and jlocal outside the foo function
Value of global variable is=10
Value of local variable to main() is=25
Enter fullscreen mode Exit fullscreen mode

13. If there is a global variable and a local variable with the same name, which one gets precedence?

If both variables are present in the same function, the local variable takes precedence over the global variable. Outside of the function, the local variable goes out of scope, and the global variable remains available to use.

14. What is recursion?

Recursion is a technique in which a function calls itself, either directly or via other functions. A function that employs recursion is called a recursive function. Although every recursive function can always be converted into an iterative (non-recursive) function, recursion is usually preferred as it significantly shortens the length of code and makes it simple to understand.

In contrast, it is recommended not to use recursion on the embedded, resource-constrained devices as each recursive call needs additional call-stack memory. Thus, a recursive function is usually slower and more memory-consuming compared to its iterative counterpart.

Let’s admire the simplicity of a recursive function that returns the nth Fibonacci number:

#include <iostream>

/**
* Returns the nth fibonacci number
*/

int fibonacci(int n){
  int fib;
  if (n <= 1){
    fib = n;
  } else {
    fib = fibonacci(n-1) + fibonacci(n-2);
  }
  return fib;
}
int main(){
  std::cout<<"The 6th fibonacci number is = "<<fibonacci(6)<<"\n";
  return 0;
}
Enter fullscreen mode Exit fullscreen mode
//output
The 6th fibonacci number is = 8
Enter fullscreen mode Exit fullscreen mode

15. Write a function that returns a minimum element of the input integer array

The basic logic is as follows:

  • We make the first element of the input array as our minimum.
  • We iterate from the second element of the input array. In each iteration:
    • If the current element is smaller than our previously declared minimum, then that element becomes our minimum
  • We return the minimum stored at the end of our array iteration.
#include <iostream>


/**
* Returns the minimum element of the input array.
*/
int findMin(int array[], int size) {
   int min = array[0];
   for (int curIndex=0; curIndex<size; curIndex++) {
       if (array[curIndex] < min) {
           min = array[curIndex];
       }
   }
   return min;
}


int main() {
   int array[9] = {5, 6, 7, -2, 0, -3, -1, -5, 1};
   std::cout<<"Minimum element of the array is  = "<<findMin(array, 9)<<"\n";
   return 0;
}
Enter fullscreen mode Exit fullscreen mode
//output
Minimum element of the array is  = -5
Enter fullscreen mode Exit fullscreen mode

16. What is the scope resolution operator and what does it do?

The scope resolution operator looks like this: ::. In programming we use the word "scope" to refer to the code block in which certain functions and variables can be accessed. The scope resolution operator allows a member variable and a derived class type to have the same name. The :: operator resolves any ambiguity when the code reaches the compiler. According to the operator, whatever comes before it is a typename, namespace, or global namespace.

As opposed to the . operator which communicates whatever comes before it as an object.

17. What is a two-dimensional array? How are they declared?

Basic arrays are one-dimensional lists of data, but any data tables that we are familiar with require two dimensions. An Excel table is an example of a two-dimensional array.

The syntax to declare a two-dimensional array looks like this:

data_type array_name [dimension1] [dimension2]

data_type: the type of data to be stored in the array

array_name: what the array will be named/stored as

[dimensionN]: The sizes of each dimension of the array

By following the syntax, we can also create an array of higher than two dimensions.

18. Explain the difference between formal and actual parameters

Formal parameters are the variables that receive values when the function is called. Actual parameters are the values that are passed to the function when it is called.

In the example below, variables x and y are the formal parameters of function printSum whereas, 3 and 5 are the actual parameters that are passed to that function.

#include <iostream>


//x and y are formal parameters
void printSum(int x, int y) {
   std::cout << x + y << std::endl;
}


int main() {
   printSum(3, 5);  // actual parameters: 3 and 5


   return 0;
}
Enter fullscreen mode Exit fullscreen mode
//output
8
Enter fullscreen mode Exit fullscreen mode

19. What happens if you try to overwrite the value of a constant?

Once declared, constant variables in C++ cannot be changed. If you try to overwrite the value of a const nothing will change and the compiler will give an error message. One way to overwrite the value of a constant after it is declared is to use the const_cast operator. There are other potential methods for overwriting the values of const variables, but they are usually not recommended.

const int constant_value = 10;


int main() {
   constant_value = 20;  // This will result in a compiler error
   return 0;
}
Enter fullscreen mode Exit fullscreen mode
//output
main.cpp: In function int main():
main.cpp:5:19: error: assignment of read-only variable constant_value
    constant_value = 20;  // This will result in a compiler error
Enter fullscreen mode Exit fullscreen mode

20. Swap the values of two variables

There are many different ways to swap the values of two variables in C++. The most common are probably to use a third variable or to use the swap() function.

Below is example code showcasing the syntax of the swap() function.

#include <bits/stdc++.h>
using namespace std;

int main(){
    int x = 12, y = 24;
    cout << "The value of x before: " << x << "\n";
    cout << "The value of y before: " << y << "\n";

    swap(x,y);
    //this function swaps the values of x and y and returns nothing
    cout << "The value of x now: " << x << "\n";
    cout << "The value of y now: " << y << "\n";
    return 0;
}
Enter fullscreen mode Exit fullscreen mode
//output
The value of x before: 12
The value of y before: 24
The value of x now: 24
The value of y now: 12
Enter fullscreen mode Exit fullscreen mode

Next steps to nail any coding interview

Hopefully, you got some use out of these C++ questions and answers. It’s crucial that you test yourself when preparing for an interview. That said, spending a lot of time studying and attempting practice questions isn’t the most efficient way to prep. Almost every single technical interview asks questions that are built on larger coding interview patterns.

Educative offers courses for learning 24 of the most common interview patterns in five top languages. Check out our series on Grokking Coding Interview Patterns and nail your next technical interview.

Happy learning!

Continue reading about C++ on Educative

Start a discussion

What are some other great C++ interview questions to practice for beginners? Was this article helpful? Let us know in the comments below!

Oldest comments (0)