C++ Interview Questions
From CS247 midterm prep:
Short Questions
- Describe the conditions under which a method call uses the static type vs when it uses the dynamic type.
- If the method call is on an object, it will always use the static type
- If the method call is on a reference or a pointer, it will:
- use the dynamic type if the method is virtual
- use the static type if the method is non-virtual
- Explain why we prefer to put implementations in a
.cc
file vs in a.h
file.- Because every time we modify the
.h
file, the linker needs to recompile every.cc
file that includes that.h
file, whereas if the implementation in is a.cc
file, the compiler only needs to recompile that particular.cc
file. See Compilation (C++)
- Because every time we modify the
- Describe at a high level how a templated class is compiled.
- At compile time, for each use of
class<T>
, the compiler makes a copy of the class with typeT
substituted as necessary. Then, it compiles as usual.
- At compile time, for each use of
- Define in your own words what an invariant is.
- Itâs something about a class / ADT that we expect to always be true
- Describe the steps of the Object Construction sequence. How do they relate to those of the Object Destruction sequence?
- Space is allocated
- Parent Constructor is called
- MIL called to initialize fields
- Constructor Body runs
- For destructor, everything runs in reverse order. The fields are destructed in reverse order that they were declared in.
- What is the difference between Overloading and Overriding?
- When we are overloading a function, we are providing multiple implementations of the same function for a different number and types of arguments.
- When we are overriding a function, we are replacing the function of the superclass with a new implementation
- NOT SURE Give two differences between overloading operators as a method vs. as a standalone function.
- When you overload operator as a method, you donât need to worry about declaring as a friend, as the overloaded method has access to the private fields
- The signature of the function changes (differing number of arguments â if inside the class, you only need the RHS, since
*this
is the LHS)
- Give one example where an operator overload has to be defined as a standalone function, and one where it has to be defined as a method.
- Standalone function:
istream& operator>>(istream&, int x) {}
- Method:
operator=
- Standalone function:
- Explain the different situations where we would prefer pass-by-value, pass-by-reference, and pass-by constant-reference.
- Pass-by-value when you wish to make a copy of the value passed
- Pass-by-reference when you wish to mutate the original variable
- Pas-by-const-reference when wish to pass a reference to the original variable, but not allow modification
- Give the definition of an lvalue, give the definition of an rvalue.
- lvalue: variable that has a memory address associated with it
- rvalue: variable that does not have a memory address
- Describe the mechanism behind the copy-swap idiom, and why one one may wish to use it.
- copy constructor and copy assignment operator may be very similar. Therefore, one should probably use the copy and swap idiom:
Node(const Node& n): data{n.data}, next{n.next == nullptr ? nullptr : new Node{n.next}} { }
Node& operator=(const Node& n) {
Node tmp{n};
swap(data, n.data);
swap(next, n.next);
return *this;
}
- For a container class C, list what methods must be defined to implement an iterator for C.
begin()
andend()
methods- For the iterator:
operator++
andoperator!=
- List two advantages to using a Makefile for build automation
- Automatic linking
- Explain differences between the waterfall and agile methodology of software development.
- waterfall: the client gives specifications, and the engineers build out the specifications
- agile: It is an interactive process comprised of sprints, where the work is done in 1-2 weeks
- Describe the conditions that indicate an owns-a relationship, and a has-a relationship
- owns a is indicated a solid diamond, called Composition. If A dies, B dies. Usually implemented via member fields
- has-a is indicated with an empty diamond, also called Aggregation. If A dies, B lives on. Usually implemented via references or non-owning pointers
- (3rd) is-a is indicated with an empty arrow, also just called Specialization. If B is-a A, then anywhere where we expect A, we can replace with B. Usually implemented via inheritance.
Coding Questions
2 Coding Questions
- Implement the Big 5 for a doubly linked list. Do so using a Node with fields
Node* next
andNode* prev
. - Transform this implementation to be well encapsulated via a DoublyLinkedList class that only exposes public methods.
- Having implemented the big 5 for the doubly linked list, implement a bi-directional iterator. A bidirectional iterator allows both ++it to take you to the next element, as well as â-it to take you to the previous element.
- Implement a reverse iterator for your linked list. Reverse iterators can be created using rbegin() and rend(). They start at the end of the data structure, and ++it takes them to the previous element.
- Consider a class RepeatedString, which contains a string s and a positive integer k. For a RepeatedString rs, implement overloads so that the following code performs the desired behaviour:
- A single constructor that allows both default construction (with s set to the empty string and k set to 0), as well as construction given the string s and int k
cout << rs
which prints the stringrs.s
k
times.cin >> rs
which should read in a strings
- For integer
j
,rs * j
andj * rs
which creates a RepeatedString with the same string, and associated integerk â j
.
- Consider creating a chess game. Consider how you may represent different pieces using an inheritance hierarchy. Each piece should have a column and row field that range from 0 to 7, and also a 2D board that allows them to determine whether a piece is occupied at a particular location. Implement a virtual method getMoves that returns a vector of possible coordinates a given piece could move to. Do so for each possible piece on the chessboard, keeping in mind that shared logic should be abstracted into the base class where possible.
Question Part 2 (from finals of CS247)
1 Short Answer Questions
- Describe the difference between virtual and multiple inheritance
- Virtual inheritance is about ensuring that only one copy of the base class is made by the derived grandchild classes
- Multiple Inheritance is the idea that a derived class can inherit from multiple base classes
- Describe how the compiler provided big 5 operate when using inheritance
- Suffers from partial assignment problem (do to no virtual keyword), and mixed assignment problem (due to virtual keyword, and overloaded in child). Fixed by using Abstract Base Class, and protected
operator=
- Suffers from partial assignment problem (do to no virtual keyword), and mixed assignment problem (due to virtual keyword, and overloaded in child). Fixed by using Abstract Base Class, and protected
- Describe the conditions necessary to overload a method
- Different number of arguments or different type of arguments
- Explain some ways of performing error handling apart from using exceptions, and give their drawbacks
- Using sentinel values: Hard to determine a valid sentinel value for other types
- Using global variables: Limited # of errors, and might be overwritten
- Define stack-unwinding. How does it relate to the concept of RAII?
- Stack unwinding is used for exception handling, to find the appropriate handler. Stack unwinding ensures that the destructors are called for all objects constructed within the scope of the try block, which ensures proper resource cleanup. This aligns with RAII by managing resources and calling the necessary cleanup code automatically.
- RAII means that an objectâs lifecycle is tied to its resource management. When object goes out of scope, the destructor is automatically called
- Why do we re-throw exceptions with âthrowâ rather than âthrow eâ?
- Because we lose the dynamic type when we copy construct.
- What type of error occurs when copying a
unique_ptr
? Run-time or compile-time? Why?- Compile-time, because the copy constructor is disabled using the = delete keyword
- What is the purpose of employing design patterns?
- To have reusable solutions to common problems
- Draw the UML for each of the design patterns discussed in the course: observer, decorator, strategy, visitor, adapter, command.
- DO on paper
- List the four types of casts in C++, and explain the purpose and limitations of each. Why do we prefer C++ casts over C-style casts?
static_cast
: conversion between well-defined typesdynamic_cast
: conversion between polymorphic types in an inheritance hierarchyconst_cast
: remove constnessreinterpret_cast
: Allows for poorly defined implementation-dependent casts
- Explain why
dynamic_cast
only works for classes with at least one virtual method defined.- For dynamic dispatching to work, it needs to look for the vtable
- Give an example of a program design that is highly cohesive but also highly coupled. Give an example of a program design that is lowly coupled but also lowly cohesive. 1.
- List the 5 SOLID design principles. Give a brief description of each principle, as well as the benefits of applying the principle to your code.
- Single Responsibility Principle: Each class should only implement one core functionality
- Open-Closed Principle: Each class should be open to extension, but closed to modification
- Liskov Substitution Principle: Substituting a superclass object with a derived subclass object should still keep the program in a valid state
- Interface Segregation Principle: Classes should only depend on methods that they use, else if creates needless Coupling
- Dependency Inversion Principle: High-level modules should not depend on low-level modules - instead, they should depend on an abstraction
- Give an example of a design that does not follow the Open/Closed principle. How could the design be adjusted to follow the principle?
- Explain the purpose of the template method pattern. Give an example of how you could rewrite a program to follow the template method pattern.
- Explain how private/protected inheritance work
- Private: all public and protected members become private
- protected: all public and protected become protected
- Assume there is a class A with some fields, and no virtual methods. B inherits from A, with some fields of itâs own. Draw a memory diagram for a B object. How does it change when you introduce a virtual method to A? How does it change when you introduce multiple inheritance? Multiple virtual inheritance?
- Give two uses of the visitor pattern.
- Method that depends on 2 polymorphic types
- Add additional functionality, without modifying the classes themselves
- Give two uses of the CRTP pattern. What special considerations are needed when using it in a pre-established inheritance hierarchy?
- Reduce boilerplate code while maintaining compile time polymorphism
- Enable polymorphic cloning
- Define the 4 levels of exception safety guarantee
- No exception guarantee: No guarantees if exception is thrown, program might or might not crash
- Basic Guarantee: If exception is thrown, program is valid, but unspecified state
- Strong Guarantee: If exception is thrown, program is valid, and program reverts to state prior to method being run
- Nothrow guarantee: Exceptions are never propagated outside of the function call
- What is the benefit to labelling methods noexcept? If a method is noexcept, does that mean it necessarily provides the nothrow guarantee?
2 Coding Questions
- Write a full implementation of shared_ptr. It should have a default constructor, a constructor taking in a ptr of type T, and support all big 5 operations, as well as an overloaded dereference operator.
- A class that defines operator< can define the other methods in terms of the < operator. For example: (a > b) is equivalent to (b < a). (a == b) is equivalent to !(a < b) && !(b < a). Write a CRTP class Compareable. Compareable should add the various comparison operators to a class that supports operator<. Give an example of a class that implements operator< and show how Compareable can be used with it. Explain why one might prefer this over an abstract class âAbstractCompareableâ that defines the various comparison operators in terms of <, and defines operator< as a virtual method to be overridden in the subclass.
- Consider making the game of Chess. Mock up an inheritance hierarchy in UML where a computer class uses the strategy pattern to make moves depending on the difficulty level of the AI. Implement this in C++.
- Consider a hierarchy representing a file system. We could have a superclass Entry, then subclasses for things like Files, Directories, links, network devices, etc. Write a hierarchy including at least Entry, File, and Directory, with an accept method taking in a visitor. Write visitors to count the number of bytes in a directory/file, and one to print out all the file names in a directory recursively.
- Consider performing manipulations to a string via the command pattern. You start with some initial string
s
, then have different commands such as Slice (which returns a substring of s given some starting and ending index), Insert (which inserts a string t into s at some index), and Repeat (which causes s to repeat n times). Implement these commands via the Command pattern, along with an Invoker and the ability to undo each command. Try implementing it in the simple way (the invoker simply keeps a history of the state of the string in-between each command) and in the memory efficient way (the commands have code and extra fields to undo their action).
My own questions
- What is Forward Declaration?
- This is when you only declare classes and functions, without the definition, so that the compiler only needs about the declaration. During the linking stage, the linker will figure out where the implementation of the functions.
- Give the 4 steps of construction
- Give the 4 steps of destruction
Other Questions
From TRON25 list
- Explain how Smart Pointers work in C++ and what their use/attributes are (unique pointers, shared pointers)
- What are access specifiers in C++?
- Difference between static and shared libraries in C
- Name all the C++ containers you know and how to use them
- Demonstrate (live on a code editor) how inheritance works in C++
- Difference between pass-by-reference and pass-by-value in C++ and when would you use either
- What is the purpose of the static keyword in C
- Can static variables be accessed by another file?
- How would you dynamically create a new object?
- What is a pure virtual function and how is it related to polymorphism?
- Why should implementations be restricted to source files? Are there potential pitfalls if not?
- What is memory corruption and leaks. What debugging tools do you use to find such problems?
- Create a virtual class function and pure virtual class function, explain the difference and usages of both
From Reddit
- Understand the differences between stl container (
std::vector
) vs stl aggregates (std::array
) - The cost of dynamic memory allocation
- The cost of dynamic polymorphism
- Moving vs copying vs passing reference
IndiaBix Test
https://www.indiabix.com/online-test/cpp-programming-test/251