2023 C++ Interview Questions - IQCode

Overview of C++ and Common Interview Questions for Freshers

C++ is a popular and powerful programming language extension of C, designed by Bjarne Stroustrup at Bell Labs. It is among the fastest object-oriented programming languages and widely used in the development of servers and games. There are also various other real-world applications, including banking, database software, operating systems, and graphics processing. In this article, we will discuss some common C++ interview questions for beginners, intermediates, and advanced level.

C++ Interview Questions for Freshers:

1. Can you name the different data types available in C++?

Differences Between C and C++

C and C++ are both programming languages, but there are some key differences between them:

  • C is a procedural language while C++ is an object-oriented language.
  • C++ has additional features like classes, inheritance, and polymorphism, which are not present in C.
  • C++ is a superset of C, meaning that C++ programs can use most of the C libraries and functions.
  • C is mostly used for system-level programming whereas C++ is used for application-level programming.
  • C++ is generally more complex and has a steeper learning curve than C.

// Example C code
#include <stdio.h>

int main() {
  printf("Hello World!");
  return 0;
}

// Example C++ code
#include <iostream>

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


Explanation of Classes and Objects in C++

Classes are a fundamental component in object-oriented programming (OOP) as they allow for the creation of custom data types. They serve as templates that define how objects of that class will behave and what data members they will contain. Objects, on the other hand, are instances of a class, meaning that they are created from the blueprint provided by the class. Objects have access to the methods and data members of their respective class and can interact with them accordingly.


// Example of a basic class and object in C++
class Car {
  private:
    string model;
    int year;
  public:
    void setModel(string modelName) {
      model = modelName;
    }
    string getModel() {
      return model;
    }
    void setYear(int modelYear) {
      year = modelYear;
    }
    int getYear() {
      return year;
    }
};
int main() {
  // Creating an object of the Car class
  Car myCar;
  myCar.setModel("Mustang");
  myCar.setyear(2021);

  // Accessing object data members and methods
  cout << "My car is a " << myCar.getModel() << " from the year " << myCar.getYear() << "." << endl;
  return 0;
}

What's the Difference Between Struct and Class?

In C++, a struct and a class are both used to define a custom data type, but there are some key differences between them.

A struct is usually used to group related data while a class is used to group related data and functions. Additionally, by default, members of a struct are public while members of a class are private.

Here's an example of how to define a struct and a class in C++:

struct Person { std::string name; int age; };

class Car { private: std::string make; std::string model; public: void drive() { std::cout << "Driving the " << make << " " << model << std::endl; } };

In this example, the Person struct simply groups together a name and an age, while the Car class groups together a make and a model, as well as providing a function to drive the car.

It's worth noting that structs can have member functions as well, and classes can have public members. However, in general, struct and class are used for different purposes, and it's a good idea to choose the right one for the job.

What is Operator Overloading?

In object-oriented programming languages like C++, operator overloading refers to the practice of defining how an operator works when applied to instances of a class. The operator can be used to perform specific operations on objects, like addition, subtraction, and comparison. By overloading operators, programmers can create more intuitive code that is easier to read and write.

PolyMorphism in C++

Polymorphism is a key feature of object-oriented programming that allows objects of different classes to be treated as if they were objects of the same class. This means that you can create a function that can take in different types of objects and still perform the same operation on all of them.

In C++, there are two types of polymorphism: compile-time polymorphism and runtime polymorphism. Compile-time polymorphism is achieved through function overloading and operator overloading, while runtime polymorphism is achieved through virtual functions and inheritance.

Function overloading allows for the creation of multiple functions with the same name but different parameter lists, while operator overloading allows for the use of C++ operators on user-defined objects. Virtual functions, on the other hand, allow for the creation of a base class with virtual functions that can be overridden by derived classes.

Overall, polymorphism is a powerful tool in C++ that allows for increased flexibility and code reuse in object-oriented programming.

Constructor in C++

In C++, a constructor is a special member function that is called automatically when an object is created. The primary purpose of a constructor is to initialize the object's data members and allocate any necessary resources.

Here is a simple example of a constructor for a class named "Person" that has two data members, "name" and "age":


class Person {
   public:
      Person(string personName, int personAge) { //Constructor definition
         name = personName;
         age = personAge;
      }
   private:
      string name;
      int age;
}

In this example, the constructor takes two arguments: a string for the person's name and an integer for their age. Inside the constructor definition, the values of these arguments are assigned to the object's "name" and "age" data members.

Constructors are very useful for creating objects with initial values and ensuring that any necessary resources are allocated properly. They can also be overloaded to provide multiple ways of initializing objects.H3 tag: Virtual Functions in C++

Virtual functions are used in C++ to achieve runtime polymorphism. They are defined in the base class using the virtual keyword and can be overridden in the derived classes. When a virtual function is called using a base class pointer or reference, the function call is resolved at runtime based on the type of the object pointed to or referred to.

Example code:

Code:

c++
#include <iostream>
using namespace std;

class Shape {
public:
    virtual void draw() {
        cout << "Drawing Shape" << endl;
    }
};

class Circle : public Shape {
public:
    void draw() override {
        cout << "Drawing Circle" << endl;
    }
};

class Square : public Shape {
public:
    void draw() override {
        cout << "Drawing Square" << endl;
    }
};

int main() {
    Shape* s1 = new Circle();
    Shape* s2 = new Square();

    s1->draw();
    s2->draw();

    delete s1;
    delete s2;

    return 0;
}

In the above code, the `Shape` class has a virtual function `draw()`. The `Circle` and `Square` classes inherit from the `Shape` class and override the `draw()` function. In the `main()` function, we create objects of the `Circle` and `Square` classes and then call the `draw()` function using base class pointers. The output of the program is:


Drawing Circle
Drawing Square

This demonstrates how virtual functions allow us to achieve polymorphic behavior in C++.

Comparison of Compile-time Polymorphism and Runtime Polymorphism

Compile-time polymorphism, also known as static polymorphism, is when the program binds the function calls during the compile-time. It is accomplished using function overloading and operator overloading. The compiler needs to know the type of object at compile-time before binding the appropriate function call to it. This type of polymorphism is efficient and faster than runtime polymorphism.

On the other hand, runtime polymorphism, also known as dynamic polymorphism, is when the function calls are resolved during the run-time. It is achieved by inheritance and virtual functions. In this type of polymorphism, the function call is decided based on the actual type of the object. This type of polymorphism has more overhead than compile-time polymorphism and is relatively slower in performance.

Both compile-time and runtime polymorphism are helpful in their ways. Choosing the correct approach depends on the specific use case and requirements.


 // Example of compile-time polymorphism
 int add(int x, int y) {
     return x + y;
 }
 
 double add(double x, double y) {
     return x + y;
 }
 
 // Example of runtime polymorphism
 class Shape {
 public:
     virtual void draw() {}
 };
 
 class Circle : public Shape {
 public:
     void draw() override {
         // draw Circle code
     }
 };
 
 class Square : public Shape {
 public:
     void draw() override {
         // draw Square code
     }
 };
 
 int main() {
     Shape* shape;
     
     shape = new Circle;
     shape->draw(); // draws Circle
     
     shape = new Square;
     shape->draw(); // draws Square
     
     return 0;
 }

What are Friend Classes and Friend Functions in C++?

In C++, a friend is a class or function that has access to the private and protected members of another class. Friend classes and functions are used to provide selective access to class members.

A friend class can access the private and protected members of the class that declares it as a friend. A friend function, on the other hand, is a non-member function that is granted access to the private and protected members of a class if it is declared as a friend in the class definition.

Friend classes and functions are commonly used in situations where encapsulation is desired but there is a need to allow certain external functions or classes to access the private or protected members of the class.

Here is an example of how to declare a friend function:


class MyClass {
  private:
    int myPrivateMember;
  friend int friendFunction(MyClass obj); // friend function declaration
};

int friendFunction(MyClass obj) {
  return obj.myPrivateMember; // friend function has access to private member
}

In the example above, we declare a function called `friendFunction` as a friend function in the class `MyClass`. This function can then access the private member `myPrivateMember` of any instance of the `MyClass` class.

It's important to note that friend classes and functions should be used sparingly and only when necessary. Improper use of friend declarations can break encapsulation and undermine the benefits of object-oriented programming.

C++ Access Specifiers

In C++, access specifiers are used to restrict the access to class members. There are three access specifiers in C++: public, private, and protected.

  • Public members: can be accessed from anywhere in the program.
  • Private members: can only be accessed by the class itself and friend classes.
  • Protected members: can be accessed by the class itself, friend classes, and derived classes.

Here's an example of a class with access specifiers:


  class MyClass {
    public: // public access specifier
      int publicVar;
      
    private: // private access specifier
      int privateVar;
      
    protected: // protected access specifier
      int protectedVar;
  };

In this example,

publicVar

can be accessed from anywhere, but

privateVar

and

protectedVar

can only be accessed from within the class.

Definition of Inline Function

An inline function is a function that is defined inside its caller function and is inserted directly into the caller function's code wherever the inline function is called. This improves the performance of the program because the overhead of calling and returning from a function is eliminated.


inline int add(int a, int b){
   return a + b;
}

int main(){
   int x = 5, y = 7;
   int result = add(x,y);
}

In this example, the add() function is defined as inline, so wherever it is called, the code for the function is inserted directly into the main() function's code, eliminating the overhead of calling and returning from a function.

Reference in C++

In C++, a reference is a type of variable that acts as an alias to another object or value. It provides an alternative way to access the memory location of an object already defined in the program and allows multiple names to refer to the same location in memory, thus making it possible to modify the original object through any of its references. References are declared using an ampersand (&) symbol, and they must always be initialized when declared.

Abstraction in C++

Abstraction is a fundamental concept in object-oriented programming that focuses on representing real-world objects and their behaviors in a simplified manner. In C++, abstraction can be achieved through the use of classes and interfaces. By abstracting away unnecessary details while providing only essential information to the user, one can create more efficient and maintainable code. In simpler terms, abstraction involves hiding the implementation details of a class or function from the user and only exposing its necessary functionalities.

Is Deconstructor Overloading Possible?

In C++, it is not possible to overload the destructor, also known as the deconstructor. Unlike constructors, which are responsible for initializing an object's data members, the destructor is responsible for releasing any resources that an object utilized during its lifespan.

When the object reaches the end of its scope or is explicitly deleted, the destructor is invoked. Since there can only be one destructor for a class in C++, it cannot be overloaded with multiple versions having different parameters or access levels.

Understanding Call by Value and Call by Reference in Programming

In programming, call by value and call by reference are two methods of passing arguments to functions.

Call by value: This method creates a copy of the argument passed to the function. Any changes made to the argument inside the function are not reflected outside the function because the function only has access to the copy of the argument.

Call by reference: This method passes the memory address of the argument to the function. This means that any changes made to the argument inside the function are reflected outside the function as well because the function has direct access to the original argument.

It's important to understand the difference between call by value and call by reference because it can affect the behavior of your program. In some cases, you may want to use call by reference to manipulate values directly, while in other cases, call by value may be sufficient.

What is an Abstract Class and When Should You Use It?

An abstract class in object-oriented programming is a class that cannot be instantiated, meaning you cannot create an object from it. The primary purpose of an abstract class is to provide a base class or template for its subclasses. It contains abstract methods, which are declared but not implemented in the abstract class. These methods must be implemented in the subclasses.

Abstract classes are often used when a common base functionality needs to be shared among multiple classes, but they have different implementations for some specific methods. In such a scenario, you can define those methods as abstract methods in the abstract base class and leave the implementation to the subclasses.

Using abstract classes helps in achieving code reusability, reduces duplication, and provides a better structure to the code. It also helps in achieving loose coupling and easy maintenance of the code.

Destructors in C++

In C++, a destructor is a special member function that is called when an object is destroyed or goes out of scope. Its main purpose is to free any resources allocated by the object's constructor or during the object's lifetime.

The format of a destructor is similar to that of a constructor, but with a tilde (~) character preceding the class name. For example, if a class is named MyClass, its destructor would be written as ~MyClass().

Destructors are often used to release memory allocated by the constructor or to close files or connections opened by the object. In general, any resources that were allocated by an object should be freed in its destructor, to avoid memory leaks and other problems.

It's important to note that in C++, a destructor is automatically called when an object goes out of scope or is explicitly deleted, so it's often not necessary to call a destructor directly.

Explanation of Static Members and Static Member Functions

In object-oriented programming, static members are class variables and functions that can be accessed without creating an instance of the class. They are shared by all instances of the class and can be accessed using the class name instead of an object.

Static member variables are declared using the "static" keyword and have a single copy that's shared by all objects of the same class. They are typically used for constants, counters, or flags that need to be accessed by all instances of the class.

Static member functions are declared using the "static" keyword and can access only static member variables. They do not have access to the "this" pointer, which means they can't access non-static member variables. They are often used for utility functions that don't modify the state of the object but still need to be associated with the class.

Here's an example of a class with static members and functions:


class MyClass {
  public:
    static int myStaticVar;
    static void myStaticFunc();
  private:
    int myVar;
};

int MyClass::myStaticVar = 0;

void MyClass::myStaticFunc() {
  // do something
}

In this example, "myStaticVar" is a static member variable that's initialized to zero, and "myStaticFunc" is a static member function that can be called using the class name, like this:


MyClass::myStaticFunc();

Static members are useful when you need to share data or functionality between multiple instances of a class, or when you want to provide a utility function that doesn't require an instance of the class.

Explanation of Inheritance

Inheritance is a fundamental concept in object-oriented programming. It refers to the ability of a class to inherit properties and methods from its parent class. The parent class is also known as the base class or superclass, while the class that inherits from it is called the child class or subclass.

The child class automatically inherits all the non-private properties and methods of its parent class. This means that it can use these properties and methods as if they were defined within the child class itself. The child class can also define its own properties and methods, which will be specific to that particular class.

Inheritance can be a powerful tool for organizing and structuring code. It allows you to create a hierarchy of classes, where each class builds upon the functionality of its parent class. This can help to reduce code duplication and make your code more modular and reusable.

However, it's important to use inheritance judiciously and to avoid creating deeply nested hierarchies of classes. This can lead to code that is difficult to understand and maintain. It's also important to remember that inheritance can be overridden in the child class, so you may need to be careful about how you use it in certain situations.

C++ Interview Question for Experienced:

C++

Copy Constructor creates an object by initializing it with an object of the same class, which has been created previously. The copy constructor is used to:

  • Initialize one object from another of the same type.
  • Copy an object to pass it as an argument to a function.
  • Copy an object to return it from a function.

The syntax of the copy constructor is:

ClassName (const ClassName &old_obj); 

where

ClassName

is the name of the class and

old_obj 

is the object that is being copied.

Difference between Shallow Copy and Deep Copy

In Python, copying objects is a common operation. However, there is a difference between shallow copy and deep copy.

A shallow copy creates a new object which stores the reference of the original elements. Thus, any changes made in the copied object will also affect the original object. Shallow copy can be performed using the slicing operator, copy() method, or the built-in function called list().

A deep copy creates a new object and recursively adds the copies of nested objects present in the original elements. Therefore, changes made in the copied object will not affect the original object. Deep copy is performed using the deepcopy() method of the copy module.

It is important to understand the distinction between shallow copy and deep copy in order to modify the original objects without damaging the original data.

Difference between Virtual Functions and Pure Virtual Functions

In C++, a virtual function is a function that is declared in the base class and can be overridden by the derived class. The definition of the function is decided at runtime based on the type of object pointed by the base class pointer.

A pure virtual function, on the other hand, is a virtual function that has no implementation in the base class. It is declared in the base class and implemented by the derived classes. A class containing at least one pure virtual function is called an abstract class and cannot be instantiated.

The key difference between virtual functions and pure virtual functions is that virtual functions have a default implementation in the base class, whereas pure virtual functions do not. In order to create an object of a class derived from an abstract class, all of the pure virtual functions in the abstract class must be implemented in the derived classes.

Order of Constructor Calls When Creating an Object of Type D Derived from Base Class B

When creating an object of type D, which is derived from base class B, the constructors of these classes would get called in the following order:

1. The constructor of B is called. 2. The constructor of D is called.

This is because the derived class constructor always calls the base class constructor first. Once the base class constructor is executed, the derived class constructor can then perform its own initialization.

Calling a Virtual Function from a Constructor

In C++, it is possible to call a virtual function from a constructor. However, doing so may not provide the expected result. When a constructor is called, the object is not yet fully initialized, so calling a virtual function may lead to unexpected behavior.

It is generally recommended to avoid calling virtual functions from constructors. If you need to initialize an object using a specific virtual function, you may consider using a separate initialization method or a factory function instead.

Explanation of Void Pointers

A void pointer is a pointer that does not have any data type associated with it. It can be used to store the address of any type of object. In C programming language, void pointers are declared using the keyword "void," and they cannot be directly dereferenced. Instead, they must be cast to a specific pointer type before they can be used to access the data they point to. Void pointers are primarily used in situations where the data type of a pointer is unknown or needs to be determined at runtime.

Understanding the "this" Pointer in C++

In C++, "this" is a keyword that represents the pointer to the object itself. It is used to refer to member variables and member functions of the class. The "this" pointer can only be used within a member function and it points to the object for which the member function is called.

For example:


class MyClass {
    private:
        int myVar;
    public:
        void setMyVar(int var) {
            this->myVar = var;
        }
};

In this code, "this->myVar" refers to the member variable "myVar" of the object that called the "setMyVar" function.

By using the "this" pointer, you can avoid naming conflicts between member variables and function parameters with the same name. It also makes the code more readable and easy to understand.

Memory Allocation and Deallocation in C++

Memory allocation and deallocation in C++ is done using the

new

and

delete

operators respectively.

To allocate memory for a single object, we use the syntax:

data_type* pointer_variable = new data_type;

For example, to allocate memory for an integer variable:

int* ptr = new int;

To free the memory allocated using

new

, we use the

delete

operator:

delete pointer_variable;

For example, to free the memory allocated for an integer variable:

delete ptr;

To allocate memory for an array of objects, we use the syntax:

data_type* pointer_variable = new data_type[size];

For example, to allocate memory for an array of 10 integers:

int* arr_ptr = new int[10];

To free the memory allocated for an array of objects:

delete[] pointer_variable;

For example, to free the memory allocated for an array of 10 integers:

delete[] arr_ptr;

It is important to remember to deallocate all dynamically allocated memory to avoid memory leaks.

Technical Interview Guides

Here are guides for technical interviews, categorized from introductory to advanced levels.

View All

Best MCQ

As part of their written examination, numerous tech companies necessitate candidates to complete multiple-choice questions (MCQs) assessing their technical aptitude.

View MCQ's
Made with love
This website uses cookies to make IQCode work for you. By using this site, you agree to our cookie policy

Welcome Back!

Sign up to unlock all of IQCode features:
  • Test your skills and track progress
  • Engage in comprehensive interactive courses
  • Commit to daily skill-enhancing challenges
  • Solve practical, real-world issues
  • Share your insights and learnings
Create an account
Sign in
Recover lost password
Or log in with

Create a Free Account

Sign up to unlock all of IQCode features:
  • Test your skills and track progress
  • Engage in comprehensive interactive courses
  • Commit to daily skill-enhancing challenges
  • Solve practical, real-world issues
  • Share your insights and learnings
Create an account
Sign up
Or sign up with
By signing up, you agree to the Terms and Conditions and Privacy Policy. You also agree to receive product-related marketing emails from IQCode, which you can unsubscribe from at any time.